@tinybirdco/sdk 0.0.3 → 0.0.6
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 +87 -14
- package/dist/api/deploy.d.ts +41 -3
- package/dist/api/deploy.d.ts.map +1 -1
- package/dist/api/deploy.js +141 -19
- package/dist/api/deploy.js.map +1 -1
- package/dist/api/deploy.test.js +77 -29
- package/dist/api/deploy.test.js.map +1 -1
- package/dist/api/local.d.ts +92 -0
- package/dist/api/local.d.ts.map +1 -0
- package/dist/api/local.js +176 -0
- package/dist/api/local.js.map +1 -0
- package/dist/api/local.test.d.ts +2 -0
- package/dist/api/local.test.d.ts.map +1 -0
- package/dist/api/local.test.js +182 -0
- package/dist/api/local.test.js.map +1 -0
- package/dist/api/resources.d.ts +178 -0
- package/dist/api/resources.d.ts.map +1 -0
- package/dist/api/resources.js +244 -0
- package/dist/api/resources.js.map +1 -0
- package/dist/api/resources.test.d.ts +2 -0
- package/dist/api/resources.test.d.ts.map +1 -0
- package/dist/api/resources.test.js +255 -0
- package/dist/api/resources.test.js.map +1 -0
- package/dist/cli/commands/build.d.ts +6 -4
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +95 -47
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/deploy.d.ts +39 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +90 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +9 -2
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +60 -31
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/init.d.ts +24 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +174 -23
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +190 -30
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/config.d.ts +14 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +7 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/config.test.js +29 -0
- package/dist/cli/config.test.js.map +1 -1
- package/dist/cli/index.js +107 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/package-manager.d.ts +8 -0
- package/dist/cli/utils/package-manager.d.ts.map +1 -0
- package/dist/cli/utils/package-manager.js +45 -0
- package/dist/cli/utils/package-manager.js.map +1 -0
- package/dist/cli/utils/package-manager.test.d.ts +2 -0
- package/dist/cli/utils/package-manager.test.d.ts.map +1 -0
- package/dist/cli/utils/package-manager.test.js +85 -0
- package/dist/cli/utils/package-manager.test.js.map +1 -0
- package/dist/codegen/index.d.ts +39 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +300 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/index.test.d.ts +2 -0
- package/dist/codegen/index.test.d.ts.map +1 -0
- package/dist/codegen/index.test.js +310 -0
- package/dist/codegen/index.test.js.map +1 -0
- package/dist/codegen/type-mapper.d.ts +20 -0
- package/dist/codegen/type-mapper.d.ts.map +1 -0
- package/dist/codegen/type-mapper.js +238 -0
- package/dist/codegen/type-mapper.js.map +1 -0
- package/dist/codegen/type-mapper.test.d.ts +2 -0
- package/dist/codegen/type-mapper.test.d.ts.map +1 -0
- package/dist/codegen/type-mapper.test.js +167 -0
- package/dist/codegen/type-mapper.test.js.map +1 -0
- package/dist/codegen/utils.d.ts +46 -0
- package/dist/codegen/utils.d.ts.map +1 -0
- package/dist/codegen/utils.js +141 -0
- package/dist/codegen/utils.js.map +1 -0
- package/dist/codegen/utils.test.d.ts +2 -0
- package/dist/codegen/utils.test.d.ts.map +1 -0
- package/dist/codegen/utils.test.js +178 -0
- package/dist/codegen/utils.test.js.map +1 -0
- package/dist/generator/index.d.ts +3 -0
- package/dist/generator/index.d.ts.map +1 -1
- package/dist/generator/index.js +17 -1
- package/dist/generator/index.js.map +1 -1
- package/dist/generator/index.test.js +104 -1
- package/dist/generator/index.test.js.map +1 -1
- package/dist/generator/loader.d.ts +15 -0
- package/dist/generator/loader.d.ts.map +1 -1
- package/dist/generator/loader.js +24 -0
- package/dist/generator/loader.js.map +1 -1
- package/dist/test/handlers.d.ts +49 -0
- package/dist/test/handlers.d.ts.map +1 -1
- package/dist/test/handlers.js +45 -0
- package/dist/test/handlers.js.map +1 -1
- package/package.json +4 -2
- package/src/api/deploy.test.ts +135 -34
- package/src/api/deploy.ts +203 -23
- package/src/api/local.test.ts +250 -0
- package/src/api/local.ts +270 -0
- package/src/api/resources.test.ts +332 -0
- package/src/api/resources.ts +554 -0
- package/src/cli/commands/build.ts +115 -53
- package/src/cli/commands/deploy.ts +126 -0
- package/src/cli/commands/dev.ts +81 -36
- package/src/cli/commands/init.test.ts +239 -30
- package/src/cli/commands/init.ts +243 -26
- package/src/cli/config.test.ts +47 -0
- package/src/cli/config.ts +20 -0
- package/src/cli/index.ts +120 -11
- package/src/cli/utils/package-manager.test.ts +118 -0
- package/src/cli/utils/package-manager.ts +44 -0
- package/src/codegen/index.test.ts +367 -0
- package/src/codegen/index.ts +379 -0
- package/src/codegen/type-mapper.test.ts +224 -0
- package/src/codegen/type-mapper.ts +265 -0
- package/src/codegen/utils.test.ts +221 -0
- package/src/codegen/utils.ts +174 -0
- package/src/generator/index.test.ts +121 -1
- package/src/generator/index.ts +19 -1
- package/src/generator/loader.ts +43 -0
- package/src/test/handlers.ts +58 -0
package/src/cli/commands/init.ts
CHANGED
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
import * as fs from "fs";
|
|
6
6
|
import * as path from "path";
|
|
7
|
+
import * as p from "@clack/prompts";
|
|
8
|
+
import pc from "picocolors";
|
|
7
9
|
import {
|
|
8
10
|
hasValidToken,
|
|
9
|
-
getTinybirdDir,
|
|
10
11
|
getRelativeTinybirdDir,
|
|
11
12
|
getConfigPath,
|
|
12
13
|
updateConfig,
|
|
14
|
+
type DevMode,
|
|
13
15
|
} from "../config.js";
|
|
14
16
|
import { browserLogin } from "../auth.js";
|
|
15
17
|
import { saveTinybirdToken } from "../env.js";
|
|
@@ -40,9 +42,9 @@ export type PageViewsRow = InferRow<typeof pageViews>;
|
|
|
40
42
|
`;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
|
-
* Default starter content for
|
|
45
|
+
* Default starter content for endpoints.ts
|
|
44
46
|
*/
|
|
45
|
-
const
|
|
47
|
+
const ENDPOINTS_CONTENT = `import { defineEndpoint, node, t, p, type InferParams, type InferOutputRow } from "@tinybirdco/sdk";
|
|
46
48
|
|
|
47
49
|
/**
|
|
48
50
|
* Top pages endpoint - get the most visited pages
|
|
@@ -88,7 +90,7 @@ const CLIENT_CONTENT = `/**
|
|
|
88
90
|
* Tinybird Client
|
|
89
91
|
*
|
|
90
92
|
* This file defines the typed Tinybird client for your project.
|
|
91
|
-
* Add your datasources and
|
|
93
|
+
* Add your datasources and endpoints here as you create them.
|
|
92
94
|
*/
|
|
93
95
|
|
|
94
96
|
import { createTinybirdClient } from "@tinybirdco/sdk";
|
|
@@ -97,7 +99,7 @@ import { createTinybirdClient } from "@tinybirdco/sdk";
|
|
|
97
99
|
import { pageViews, type PageViewsRow } from "./datasources";
|
|
98
100
|
|
|
99
101
|
// Import endpoints and their types
|
|
100
|
-
import { topPages, type TopPagesParams, type TopPagesOutput } from "./
|
|
102
|
+
import { topPages, type TopPagesParams, type TopPagesOutput } from "./endpoints";
|
|
101
103
|
|
|
102
104
|
// Create the typed Tinybird client
|
|
103
105
|
export const tinybird = createTinybirdClient({
|
|
@@ -115,14 +117,21 @@ export { pageViews, topPages };
|
|
|
115
117
|
/**
|
|
116
118
|
* Default config content generator
|
|
117
119
|
*/
|
|
118
|
-
function createDefaultConfig(
|
|
120
|
+
function createDefaultConfig(
|
|
121
|
+
tinybirdDir: string,
|
|
122
|
+
devMode: DevMode,
|
|
123
|
+
additionalIncludes: string[] = []
|
|
124
|
+
) {
|
|
125
|
+
const include = [
|
|
126
|
+
`${tinybirdDir}/datasources.ts`,
|
|
127
|
+
`${tinybirdDir}/endpoints.ts`,
|
|
128
|
+
...additionalIncludes,
|
|
129
|
+
];
|
|
119
130
|
return {
|
|
120
|
-
include
|
|
121
|
-
`${tinybirdDir}/datasources.ts`,
|
|
122
|
-
`${tinybirdDir}/pipes.ts`,
|
|
123
|
-
],
|
|
131
|
+
include,
|
|
124
132
|
token: "${TINYBIRD_TOKEN}",
|
|
125
133
|
baseUrl: "https://api.tinybird.co",
|
|
134
|
+
devMode,
|
|
126
135
|
};
|
|
127
136
|
}
|
|
128
137
|
|
|
@@ -136,6 +145,14 @@ export interface InitOptions {
|
|
|
136
145
|
force?: boolean;
|
|
137
146
|
/** Skip the login flow */
|
|
138
147
|
skipLogin?: boolean;
|
|
148
|
+
/** Development mode - if provided, skip interactive prompt */
|
|
149
|
+
devMode?: DevMode;
|
|
150
|
+
/** Client path - if provided, skip interactive prompt */
|
|
151
|
+
clientPath?: string;
|
|
152
|
+
/** Skip prompts for existing datafiles - for testing */
|
|
153
|
+
skipDatafilePrompt?: boolean;
|
|
154
|
+
/** Auto-include existing datafiles without prompting - for testing */
|
|
155
|
+
includeExistingDatafiles?: boolean;
|
|
139
156
|
}
|
|
140
157
|
|
|
141
158
|
/**
|
|
@@ -156,6 +173,66 @@ export interface InitResult {
|
|
|
156
173
|
workspaceName?: string;
|
|
157
174
|
/** User email after login */
|
|
158
175
|
userEmail?: string;
|
|
176
|
+
/** Selected development mode */
|
|
177
|
+
devMode?: DevMode;
|
|
178
|
+
/** Selected client path */
|
|
179
|
+
clientPath?: string;
|
|
180
|
+
/** Existing datafiles that were added to config */
|
|
181
|
+
existingDatafiles?: string[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Find existing .datasource and .pipe files in the repository
|
|
186
|
+
*
|
|
187
|
+
* @param cwd - Working directory to search from
|
|
188
|
+
* @param maxDepth - Maximum directory depth to search (default: 5)
|
|
189
|
+
* @returns Array of relative file paths
|
|
190
|
+
*/
|
|
191
|
+
export function findExistingDatafiles(
|
|
192
|
+
cwd: string,
|
|
193
|
+
maxDepth: number = 5
|
|
194
|
+
): string[] {
|
|
195
|
+
const files: string[] = [];
|
|
196
|
+
|
|
197
|
+
function searchDir(dir: string, depth: number): void {
|
|
198
|
+
if (depth > maxDepth) return;
|
|
199
|
+
|
|
200
|
+
let entries: fs.Dirent[];
|
|
201
|
+
try {
|
|
202
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
203
|
+
} catch {
|
|
204
|
+
return; // Skip directories we can't read
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
for (const entry of entries) {
|
|
208
|
+
const fullPath = path.join(dir, entry.name);
|
|
209
|
+
|
|
210
|
+
// Skip node_modules and hidden directories
|
|
211
|
+
if (
|
|
212
|
+
entry.isDirectory() &&
|
|
213
|
+
(entry.name === "node_modules" ||
|
|
214
|
+
entry.name.startsWith(".") ||
|
|
215
|
+
entry.name === "dist" ||
|
|
216
|
+
entry.name === "build")
|
|
217
|
+
) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (entry.isDirectory()) {
|
|
222
|
+
searchDir(fullPath, depth + 1);
|
|
223
|
+
} else if (
|
|
224
|
+
entry.isFile() &&
|
|
225
|
+
(entry.name.endsWith(".datasource") || entry.name.endsWith(".pipe"))
|
|
226
|
+
) {
|
|
227
|
+
// Convert to relative path
|
|
228
|
+
const relativePath = path.relative(cwd, fullPath);
|
|
229
|
+
files.push(relativePath);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
searchDir(cwd, 0);
|
|
235
|
+
return files.sort();
|
|
159
236
|
}
|
|
160
237
|
|
|
161
238
|
/**
|
|
@@ -163,7 +240,7 @@ export interface InitResult {
|
|
|
163
240
|
*
|
|
164
241
|
* Creates:
|
|
165
242
|
* - tinybird.json in the project root
|
|
166
|
-
* - src/tinybird/ folder with datasources.ts,
|
|
243
|
+
* - src/tinybird/ folder with datasources.ts, endpoints.ts, and client.ts
|
|
167
244
|
*
|
|
168
245
|
* @param options - Init options
|
|
169
246
|
* @returns Init result
|
|
@@ -175,14 +252,90 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
175
252
|
|
|
176
253
|
const created: string[] = [];
|
|
177
254
|
const skipped: string[] = [];
|
|
255
|
+
let existingDatafiles: string[] = [];
|
|
256
|
+
|
|
257
|
+
// Check for existing .datasource and .pipe files
|
|
258
|
+
const foundDatafiles = findExistingDatafiles(cwd);
|
|
259
|
+
|
|
260
|
+
// Determine devMode - prompt if not provided
|
|
261
|
+
let devMode: DevMode = options.devMode ?? "branch";
|
|
262
|
+
|
|
263
|
+
if (!options.devMode) {
|
|
264
|
+
// Show interactive prompt for workflow selection
|
|
265
|
+
p.intro(pc.cyan("tinybird init"));
|
|
266
|
+
|
|
267
|
+
const workflowChoice = await p.select({
|
|
268
|
+
message: "How do you want to develop with Tinybird?",
|
|
269
|
+
options: [
|
|
270
|
+
{
|
|
271
|
+
value: "branch",
|
|
272
|
+
label: "Branches",
|
|
273
|
+
hint: "Use Tinybird Cloud with git-based branching",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
value: "local",
|
|
277
|
+
label: "Tinybird Local",
|
|
278
|
+
hint: "Run your own Tinybird instance locally",
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
if (p.isCancel(workflowChoice)) {
|
|
284
|
+
p.cancel("Init cancelled.");
|
|
285
|
+
return {
|
|
286
|
+
success: false,
|
|
287
|
+
created: [],
|
|
288
|
+
skipped: [],
|
|
289
|
+
error: "Cancelled by user",
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
devMode = workflowChoice as DevMode;
|
|
294
|
+
}
|
|
178
295
|
|
|
179
296
|
// Determine tinybird folder path based on project structure
|
|
180
|
-
const
|
|
181
|
-
|
|
297
|
+
const defaultRelativePath = getRelativeTinybirdDir(cwd);
|
|
298
|
+
let relativeTinybirdDir = options.clientPath ?? defaultRelativePath;
|
|
299
|
+
|
|
300
|
+
if (!options.clientPath && !options.devMode) {
|
|
301
|
+
// Ask user to confirm or change the client path
|
|
302
|
+
const clientPathChoice = await p.text({
|
|
303
|
+
message: "Where should we generate the Tinybird client?",
|
|
304
|
+
placeholder: defaultRelativePath,
|
|
305
|
+
defaultValue: defaultRelativePath,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (p.isCancel(clientPathChoice)) {
|
|
309
|
+
p.cancel("Init cancelled.");
|
|
310
|
+
return {
|
|
311
|
+
success: false,
|
|
312
|
+
created: [],
|
|
313
|
+
skipped: [],
|
|
314
|
+
error: "Cancelled by user",
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
relativeTinybirdDir = clientPathChoice || defaultRelativePath;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Ask about existing datafiles if found
|
|
322
|
+
if (foundDatafiles.length > 0 && !options.skipDatafilePrompt) {
|
|
323
|
+
const includeDatafiles =
|
|
324
|
+
options.includeExistingDatafiles ??
|
|
325
|
+
(await promptForExistingDatafiles(foundDatafiles));
|
|
326
|
+
|
|
327
|
+
if (includeDatafiles) {
|
|
328
|
+
existingDatafiles = foundDatafiles;
|
|
329
|
+
}
|
|
330
|
+
} else if (options.includeExistingDatafiles && foundDatafiles.length > 0) {
|
|
331
|
+
existingDatafiles = foundDatafiles;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const tinybirdDir = path.join(cwd, relativeTinybirdDir);
|
|
182
335
|
|
|
183
336
|
// File paths
|
|
184
337
|
const datasourcesPath = path.join(tinybirdDir, "datasources.ts");
|
|
185
|
-
const
|
|
338
|
+
const endpointsPath = path.join(tinybirdDir, "endpoints.ts");
|
|
186
339
|
const clientPath = path.join(tinybirdDir, "client.ts");
|
|
187
340
|
|
|
188
341
|
// Create config file (tinybird.json)
|
|
@@ -191,7 +344,11 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
191
344
|
skipped.push("tinybird.json");
|
|
192
345
|
} else {
|
|
193
346
|
try {
|
|
194
|
-
const config = createDefaultConfig(
|
|
347
|
+
const config = createDefaultConfig(
|
|
348
|
+
relativeTinybirdDir,
|
|
349
|
+
devMode,
|
|
350
|
+
existingDatafiles
|
|
351
|
+
);
|
|
195
352
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
196
353
|
created.push("tinybird.json");
|
|
197
354
|
} catch (error) {
|
|
@@ -212,7 +369,9 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
212
369
|
success: false,
|
|
213
370
|
created,
|
|
214
371
|
skipped,
|
|
215
|
-
error: `Failed to create ${relativeTinybirdDir} folder: ${
|
|
372
|
+
error: `Failed to create ${relativeTinybirdDir} folder: ${
|
|
373
|
+
(error as Error).message
|
|
374
|
+
}`,
|
|
216
375
|
};
|
|
217
376
|
}
|
|
218
377
|
|
|
@@ -233,19 +392,19 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
233
392
|
}
|
|
234
393
|
}
|
|
235
394
|
|
|
236
|
-
// Create
|
|
237
|
-
if (fs.existsSync(
|
|
238
|
-
skipped.push(`${relativeTinybirdDir}/
|
|
395
|
+
// Create endpoints.ts
|
|
396
|
+
if (fs.existsSync(endpointsPath) && !force) {
|
|
397
|
+
skipped.push(`${relativeTinybirdDir}/endpoints.ts`);
|
|
239
398
|
} else {
|
|
240
399
|
try {
|
|
241
|
-
fs.writeFileSync(
|
|
242
|
-
created.push(`${relativeTinybirdDir}/
|
|
400
|
+
fs.writeFileSync(endpointsPath, ENDPOINTS_CONTENT);
|
|
401
|
+
created.push(`${relativeTinybirdDir}/endpoints.ts`);
|
|
243
402
|
} catch (error) {
|
|
244
403
|
return {
|
|
245
404
|
success: false,
|
|
246
405
|
created,
|
|
247
406
|
skipped,
|
|
248
|
-
error: `Failed to create
|
|
407
|
+
error: `Failed to create endpoints.ts: ${(error as Error).message}`,
|
|
249
408
|
};
|
|
250
409
|
}
|
|
251
410
|
}
|
|
@@ -288,8 +447,16 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
288
447
|
modified = true;
|
|
289
448
|
}
|
|
290
449
|
|
|
450
|
+
if (!packageJson.scripts["tinybird:deploy"]) {
|
|
451
|
+
packageJson.scripts["tinybird:deploy"] = "tinybird deploy";
|
|
452
|
+
modified = true;
|
|
453
|
+
}
|
|
454
|
+
|
|
291
455
|
if (modified) {
|
|
292
|
-
fs.writeFileSync(
|
|
456
|
+
fs.writeFileSync(
|
|
457
|
+
packageJsonPath,
|
|
458
|
+
JSON.stringify(packageJson, null, 2) + "\n"
|
|
459
|
+
);
|
|
293
460
|
created.push("package.json (added tinybird scripts)");
|
|
294
461
|
}
|
|
295
462
|
} catch {
|
|
@@ -312,8 +479,9 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
312
479
|
}
|
|
313
480
|
|
|
314
481
|
// If custom base URL, update tinybird.json
|
|
315
|
-
|
|
316
|
-
|
|
482
|
+
const baseUrl = authResult.baseUrl ?? "https://api.tinybird.co";
|
|
483
|
+
if (baseUrl !== "https://api.tinybird.co") {
|
|
484
|
+
updateConfig(configPath, { baseUrl });
|
|
317
485
|
}
|
|
318
486
|
|
|
319
487
|
return {
|
|
@@ -323,15 +491,25 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
323
491
|
loggedIn: true,
|
|
324
492
|
workspaceName: authResult.workspaceName,
|
|
325
493
|
userEmail: authResult.userEmail,
|
|
494
|
+
devMode,
|
|
495
|
+
clientPath: relativeTinybirdDir,
|
|
496
|
+
existingDatafiles:
|
|
497
|
+
existingDatafiles.length > 0 ? existingDatafiles : undefined,
|
|
326
498
|
};
|
|
327
499
|
} catch (error) {
|
|
328
500
|
// Login succeeded but saving credentials failed
|
|
329
|
-
console.error(
|
|
501
|
+
console.error(
|
|
502
|
+
`Warning: Failed to save credentials: ${(error as Error).message}`
|
|
503
|
+
);
|
|
330
504
|
return {
|
|
331
505
|
success: true,
|
|
332
506
|
created,
|
|
333
507
|
skipped,
|
|
334
508
|
loggedIn: false,
|
|
509
|
+
devMode,
|
|
510
|
+
clientPath: relativeTinybirdDir,
|
|
511
|
+
existingDatafiles:
|
|
512
|
+
existingDatafiles.length > 0 ? existingDatafiles : undefined,
|
|
335
513
|
};
|
|
336
514
|
}
|
|
337
515
|
} else {
|
|
@@ -341,6 +519,10 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
341
519
|
created,
|
|
342
520
|
skipped,
|
|
343
521
|
loggedIn: false,
|
|
522
|
+
devMode,
|
|
523
|
+
clientPath: relativeTinybirdDir,
|
|
524
|
+
existingDatafiles:
|
|
525
|
+
existingDatafiles.length > 0 ? existingDatafiles : undefined,
|
|
344
526
|
};
|
|
345
527
|
}
|
|
346
528
|
}
|
|
@@ -349,5 +531,40 @@ export async function runInit(options: InitOptions = {}): Promise<InitResult> {
|
|
|
349
531
|
success: true,
|
|
350
532
|
created,
|
|
351
533
|
skipped,
|
|
534
|
+
devMode,
|
|
535
|
+
clientPath: relativeTinybirdDir,
|
|
536
|
+
existingDatafiles:
|
|
537
|
+
existingDatafiles.length > 0 ? existingDatafiles : undefined,
|
|
352
538
|
};
|
|
353
539
|
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Prompt user about including existing datafiles
|
|
543
|
+
*/
|
|
544
|
+
async function promptForExistingDatafiles(
|
|
545
|
+
datafiles: string[]
|
|
546
|
+
): Promise<boolean> {
|
|
547
|
+
const datasourceCount = datafiles.filter((f) =>
|
|
548
|
+
f.endsWith(".datasource")
|
|
549
|
+
).length;
|
|
550
|
+
const pipeCount = datafiles.filter((f) => f.endsWith(".pipe")).length;
|
|
551
|
+
|
|
552
|
+
const parts: string[] = [];
|
|
553
|
+
if (datasourceCount > 0) {
|
|
554
|
+
parts.push(`${datasourceCount} .datasource file${datasourceCount > 1 ? "s" : ""}`);
|
|
555
|
+
}
|
|
556
|
+
if (pipeCount > 0) {
|
|
557
|
+
parts.push(`${pipeCount} .pipe file${pipeCount > 1 ? "s" : ""}`);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const confirmInclude = await p.confirm({
|
|
561
|
+
message: `Found ${parts.join(" and ")} in your project. Include them in tinybird.json?`,
|
|
562
|
+
initialValue: true,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
if (p.isCancel(confirmInclude)) {
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return confirmInclude;
|
|
570
|
+
}
|
package/src/cli/config.test.ts
CHANGED
|
@@ -267,6 +267,53 @@ describe("Config", () => {
|
|
|
267
267
|
|
|
268
268
|
expect(() => loadConfig(tempDir)).toThrow("Failed to parse");
|
|
269
269
|
});
|
|
270
|
+
|
|
271
|
+
it("defaults devMode to branch when not specified", () => {
|
|
272
|
+
const config = {
|
|
273
|
+
include: ["lib/datasources.ts"],
|
|
274
|
+
token: "test-token",
|
|
275
|
+
};
|
|
276
|
+
fs.writeFileSync(
|
|
277
|
+
path.join(tempDir, "tinybird.json"),
|
|
278
|
+
JSON.stringify(config)
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const result = loadConfig(tempDir);
|
|
282
|
+
|
|
283
|
+
expect(result.devMode).toBe("branch");
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it("loads devMode as branch when explicitly set", () => {
|
|
287
|
+
const config = {
|
|
288
|
+
include: ["lib/datasources.ts"],
|
|
289
|
+
token: "test-token",
|
|
290
|
+
devMode: "branch",
|
|
291
|
+
};
|
|
292
|
+
fs.writeFileSync(
|
|
293
|
+
path.join(tempDir, "tinybird.json"),
|
|
294
|
+
JSON.stringify(config)
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
const result = loadConfig(tempDir);
|
|
298
|
+
|
|
299
|
+
expect(result.devMode).toBe("branch");
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it("loads devMode as local when set", () => {
|
|
303
|
+
const config = {
|
|
304
|
+
include: ["lib/datasources.ts"],
|
|
305
|
+
token: "test-token",
|
|
306
|
+
devMode: "local",
|
|
307
|
+
};
|
|
308
|
+
fs.writeFileSync(
|
|
309
|
+
path.join(tempDir, "tinybird.json"),
|
|
310
|
+
JSON.stringify(config)
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
const result = loadConfig(tempDir);
|
|
314
|
+
|
|
315
|
+
expect(result.devMode).toBe("local");
|
|
316
|
+
});
|
|
270
317
|
});
|
|
271
318
|
|
|
272
319
|
describe("updateConfig", () => {
|
package/src/cli/config.ts
CHANGED
|
@@ -6,6 +6,13 @@ import * as fs from "fs";
|
|
|
6
6
|
import * as path from "path";
|
|
7
7
|
import { getCurrentGitBranch, isMainBranch, getTinybirdBranchName } from "./git.js";
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Development mode options
|
|
11
|
+
* - "branch": Use Tinybird cloud with branches (default)
|
|
12
|
+
* - "local": Use local Tinybird container at localhost:7181
|
|
13
|
+
*/
|
|
14
|
+
export type DevMode = "branch" | "local";
|
|
15
|
+
|
|
9
16
|
/**
|
|
10
17
|
* Tinybird configuration file structure
|
|
11
18
|
*/
|
|
@@ -18,6 +25,8 @@ export interface TinybirdConfig {
|
|
|
18
25
|
token: string;
|
|
19
26
|
/** Tinybird API base URL (optional, defaults to EU region) */
|
|
20
27
|
baseUrl?: string;
|
|
28
|
+
/** Development mode: "branch" (default) or "local" */
|
|
29
|
+
devMode?: DevMode;
|
|
21
30
|
}
|
|
22
31
|
|
|
23
32
|
/**
|
|
@@ -40,6 +49,8 @@ export interface ResolvedConfig {
|
|
|
40
49
|
tinybirdBranch: string | null;
|
|
41
50
|
/** Whether we're on the main/master branch */
|
|
42
51
|
isMainBranch: boolean;
|
|
52
|
+
/** Development mode: "branch" or "local" */
|
|
53
|
+
devMode: DevMode;
|
|
43
54
|
}
|
|
44
55
|
|
|
45
56
|
/**
|
|
@@ -47,6 +58,11 @@ export interface ResolvedConfig {
|
|
|
47
58
|
*/
|
|
48
59
|
const DEFAULT_BASE_URL = "https://api.tinybird.co";
|
|
49
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Local Tinybird base URL
|
|
63
|
+
*/
|
|
64
|
+
export const LOCAL_BASE_URL = "http://localhost:7181";
|
|
65
|
+
|
|
50
66
|
/**
|
|
51
67
|
* Config file name
|
|
52
68
|
*/
|
|
@@ -243,6 +259,9 @@ export function loadConfig(cwd: string = process.cwd()): ResolvedConfig {
|
|
|
243
259
|
const gitBranch = getCurrentGitBranch();
|
|
244
260
|
const tinybirdBranch = getTinybirdBranchName();
|
|
245
261
|
|
|
262
|
+
// Resolve devMode (default to "branch")
|
|
263
|
+
const devMode: DevMode = config.devMode ?? "branch";
|
|
264
|
+
|
|
246
265
|
return {
|
|
247
266
|
include,
|
|
248
267
|
token: resolvedToken,
|
|
@@ -252,6 +271,7 @@ export function loadConfig(cwd: string = process.cwd()): ResolvedConfig {
|
|
|
252
271
|
gitBranch,
|
|
253
272
|
tinybirdBranch,
|
|
254
273
|
isMainBranch: isMainBranch(),
|
|
274
|
+
devMode,
|
|
255
275
|
};
|
|
256
276
|
}
|
|
257
277
|
|