@tinybirdco/sdk 0.0.7 → 0.0.9
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/dist/api/resources.d.ts +2 -0
- package/dist/api/resources.d.ts.map +1 -1
- package/dist/api/resources.js +1 -0
- package/dist/api/resources.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +301 -205
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/init.test.js +67 -93
- package/dist/cli/commands/init.test.js.map +1 -1
- package/dist/cli/config.d.ts +3 -7
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +9 -20
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/config.test.js +11 -29
- package/dist/cli/config.test.js.map +1 -1
- package/dist/cli/git.d.ts +5 -0
- package/dist/cli/git.d.ts.map +1 -1
- package/dist/cli/git.js +15 -0
- package/dist/cli/git.js.map +1 -1
- package/dist/cli/index.js +42 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/package-manager.d.ts +9 -0
- package/dist/cli/utils/package-manager.d.ts.map +1 -1
- package/dist/cli/utils/package-manager.js +130 -35
- package/dist/cli/utils/package-manager.js.map +1 -1
- package/dist/cli/utils/package-manager.test.js +124 -32
- package/dist/cli/utils/package-manager.test.js.map +1 -1
- package/dist/codegen/index.d.ts +4 -0
- package/dist/codegen/index.d.ts.map +1 -1
- package/dist/codegen/index.js +96 -0
- package/dist/codegen/index.js.map +1 -1
- package/dist/codegen/index.test.js +10 -0
- package/dist/codegen/index.test.js.map +1 -1
- package/dist/generator/datasource.d.ts.map +1 -1
- package/dist/generator/datasource.js +20 -0
- package/dist/generator/datasource.js.map +1 -1
- package/dist/generator/datasource.test.js +11 -0
- package/dist/generator/datasource.test.js.map +1 -1
- package/dist/schema/datasource.d.ts +5 -0
- package/dist/schema/datasource.d.ts.map +1 -1
- package/dist/schema/datasource.js.map +1 -1
- package/package.json +1 -1
- package/src/api/resources.ts +4 -0
- package/src/cli/commands/init.test.ts +67 -107
- package/src/cli/commands/init.ts +350 -218
- package/src/cli/config.test.ts +12 -42
- package/src/cli/config.ts +9 -23
- package/src/cli/git.ts +15 -0
- package/src/cli/index.ts +46 -27
- package/src/cli/utils/package-manager.test.ts +165 -33
- package/src/cli/utils/package-manager.ts +133 -30
- package/src/codegen/index.test.ts +12 -0
- package/src/codegen/index.ts +120 -0
- package/src/generator/datasource.test.ts +13 -0
- package/src/generator/datasource.ts +24 -0
- package/src/schema/datasource.ts +5 -0
|
@@ -5,13 +5,37 @@ import * as fs from "fs";
|
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import * as p from "@clack/prompts";
|
|
7
7
|
import pc from "picocolors";
|
|
8
|
-
import { hasValidToken, getRelativeTinybirdDir, getConfigPath, updateConfig, } from "../config.js";
|
|
8
|
+
import { hasValidToken, getRelativeTinybirdDir, getConfigPath, updateConfig, loadConfig, } from "../config.js";
|
|
9
9
|
import { browserLogin } from "../auth.js";
|
|
10
10
|
import { saveTinybirdToken } from "../env.js";
|
|
11
|
+
import { getGitRoot } from "../git.js";
|
|
12
|
+
import { fetchAllResources } from "../../api/resources.js";
|
|
13
|
+
import { generateCombinedFile } from "../../codegen/index.js";
|
|
11
14
|
/**
|
|
12
|
-
* Default starter content for
|
|
15
|
+
* Default starter content for tinybird.ts (single file with everything)
|
|
13
16
|
*/
|
|
14
|
-
const
|
|
17
|
+
const TINYBIRD_CONTENT = `/**
|
|
18
|
+
* Tinybird Definitions
|
|
19
|
+
*
|
|
20
|
+
* Define your datasources, endpoints, and client here.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
defineDatasource,
|
|
25
|
+
defineEndpoint,
|
|
26
|
+
createTinybirdClient,
|
|
27
|
+
node,
|
|
28
|
+
t,
|
|
29
|
+
p,
|
|
30
|
+
engine,
|
|
31
|
+
type InferRow,
|
|
32
|
+
type InferParams,
|
|
33
|
+
type InferOutputRow,
|
|
34
|
+
} from "@tinybirdco/sdk";
|
|
35
|
+
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Datasources
|
|
38
|
+
// ============================================================================
|
|
15
39
|
|
|
16
40
|
/**
|
|
17
41
|
* Page views datasource - tracks page view events
|
|
@@ -29,13 +53,11 @@ export const pageViews = defineDatasource("page_views", {
|
|
|
29
53
|
}),
|
|
30
54
|
});
|
|
31
55
|
|
|
32
|
-
// Row type - use this for ingesting data
|
|
33
56
|
export type PageViewsRow = InferRow<typeof pageViews>;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const ENDPOINTS_CONTENT = `import { defineEndpoint, node, t, p, type InferParams, type InferOutputRow } from "@tinybirdco/sdk";
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Endpoints
|
|
60
|
+
// ============================================================================
|
|
39
61
|
|
|
40
62
|
/**
|
|
41
63
|
* Top pages endpoint - get the most visited pages
|
|
@@ -69,39 +91,17 @@ export const topPages = defineEndpoint("top_pages", {
|
|
|
69
91
|
},
|
|
70
92
|
});
|
|
71
93
|
|
|
72
|
-
// Endpoint types - use these for calling the API
|
|
73
94
|
export type TopPagesParams = InferParams<typeof topPages>;
|
|
74
95
|
export type TopPagesOutput = InferOutputRow<typeof topPages>;
|
|
75
|
-
`;
|
|
76
|
-
/**
|
|
77
|
-
* Default starter content for client.ts
|
|
78
|
-
*/
|
|
79
|
-
const CLIENT_CONTENT = `/**
|
|
80
|
-
* Tinybird Client
|
|
81
|
-
*
|
|
82
|
-
* This file defines the typed Tinybird client for your project.
|
|
83
|
-
* Add your datasources and endpoints here as you create them.
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
import { createTinybirdClient } from "@tinybirdco/sdk";
|
|
87
96
|
|
|
88
|
-
//
|
|
89
|
-
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// Client
|
|
99
|
+
// ============================================================================
|
|
90
100
|
|
|
91
|
-
// Import endpoints and their types
|
|
92
|
-
import { topPages, type TopPagesParams, type TopPagesOutput } from "./endpoints";
|
|
93
|
-
|
|
94
|
-
// Create the typed Tinybird client
|
|
95
101
|
export const tinybird = createTinybirdClient({
|
|
96
102
|
datasources: { pageViews },
|
|
97
103
|
pipes: { topPages },
|
|
98
104
|
});
|
|
99
|
-
|
|
100
|
-
// Re-export types for convenience
|
|
101
|
-
export type { PageViewsRow, TopPagesParams, TopPagesOutput };
|
|
102
|
-
|
|
103
|
-
// Re-export entities
|
|
104
|
-
export { pageViews, topPages };
|
|
105
105
|
`;
|
|
106
106
|
const TINYBIRD_CI_WORKFLOW = `name: Tinybird CI
|
|
107
107
|
|
|
@@ -125,6 +125,7 @@ jobs:
|
|
|
125
125
|
node-version: "20"
|
|
126
126
|
cache: "pnpm"
|
|
127
127
|
- run: pnpm install --frozen-lockfile
|
|
128
|
+
- run: pnpm run tinybird:build
|
|
128
129
|
- run: pnpm run tinybird:deploy -- --check
|
|
129
130
|
env:
|
|
130
131
|
TINYBIRD_TOKEN: \${{ secrets.TINYBIRD_TOKEN }}
|
|
@@ -153,20 +154,59 @@ jobs:
|
|
|
153
154
|
node-version: "20"
|
|
154
155
|
cache: "pnpm"
|
|
155
156
|
- run: pnpm install --frozen-lockfile
|
|
157
|
+
- run: pnpm run tinybird:build
|
|
156
158
|
- run: pnpm run tinybird:deploy
|
|
157
159
|
env:
|
|
158
160
|
TINYBIRD_TOKEN: \${{ secrets.TINYBIRD_TOKEN }}
|
|
159
161
|
`;
|
|
160
|
-
const
|
|
162
|
+
const TINYBIRD_GITLAB_CI_WORKFLOW = `stages:
|
|
163
|
+
- tinybird
|
|
164
|
+
|
|
165
|
+
tinybird_ci:
|
|
166
|
+
stage: tinybird
|
|
167
|
+
image: node:20
|
|
168
|
+
rules:
|
|
169
|
+
- changes:
|
|
170
|
+
- tinybird.json
|
|
171
|
+
- src/tinybird/**
|
|
172
|
+
- tinybird/**
|
|
173
|
+
- "**/*.datasource"
|
|
174
|
+
- "**/*.pipe"
|
|
175
|
+
script:
|
|
176
|
+
- corepack enable
|
|
177
|
+
- pnpm install --frozen-lockfile
|
|
178
|
+
- pnpm run tinybird:build
|
|
179
|
+
- pnpm run tinybird:deploy -- --check
|
|
180
|
+
variables:
|
|
181
|
+
TINYBIRD_TOKEN: \${TINYBIRD_TOKEN}
|
|
182
|
+
`;
|
|
183
|
+
const TINYBIRD_GITLAB_CD_WORKFLOW = `stages:
|
|
184
|
+
- tinybird
|
|
185
|
+
|
|
186
|
+
tinybird_cd:
|
|
187
|
+
stage: tinybird
|
|
188
|
+
image: node:20
|
|
189
|
+
rules:
|
|
190
|
+
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
191
|
+
changes:
|
|
192
|
+
- tinybird.json
|
|
193
|
+
- src/tinybird/**
|
|
194
|
+
- tinybird/**
|
|
195
|
+
- "**/*.datasource"
|
|
196
|
+
- "**/*.pipe"
|
|
197
|
+
script:
|
|
198
|
+
- corepack enable
|
|
199
|
+
- pnpm install --frozen-lockfile
|
|
200
|
+
- pnpm run tinybird:build
|
|
201
|
+
- pnpm run tinybird:deploy
|
|
202
|
+
variables:
|
|
203
|
+
TINYBIRD_TOKEN: \${TINYBIRD_TOKEN}
|
|
204
|
+
`;
|
|
161
205
|
/**
|
|
162
206
|
* Default config content generator
|
|
163
207
|
*/
|
|
164
|
-
function createDefaultConfig(
|
|
165
|
-
const include = [
|
|
166
|
-
`${tinybirdDir}/datasources.ts`,
|
|
167
|
-
`${tinybirdDir}/endpoints.ts`,
|
|
168
|
-
...additionalIncludes,
|
|
169
|
-
];
|
|
208
|
+
function createDefaultConfig(tinybirdFilePath, devMode, additionalIncludes = []) {
|
|
209
|
+
const include = [tinybirdFilePath, ...additionalIncludes];
|
|
170
210
|
return {
|
|
171
211
|
include,
|
|
172
212
|
token: "${TINYBIRD_TOKEN}",
|
|
@@ -244,7 +284,7 @@ export async function runInit(options = {}) {
|
|
|
244
284
|
let devMode = options.devMode ?? "branch";
|
|
245
285
|
if (!options.devMode) {
|
|
246
286
|
// Show interactive prompt for workflow selection
|
|
247
|
-
p.intro(pc.cyan("tinybird
|
|
287
|
+
p.intro(pc.cyan("tinybird.json"));
|
|
248
288
|
const workflowChoice = await p.select({
|
|
249
289
|
message: "How do you want to develop with Tinybird?",
|
|
250
290
|
options: [
|
|
@@ -278,7 +318,7 @@ export async function runInit(options = {}) {
|
|
|
278
318
|
if (!options.clientPath && !options.devMode) {
|
|
279
319
|
// Ask user to confirm or change the client path
|
|
280
320
|
const clientPathChoice = await p.text({
|
|
281
|
-
message: "Where should we create
|
|
321
|
+
message: "Where should we create initial tinybird.ts file?",
|
|
282
322
|
placeholder: defaultRelativePath,
|
|
283
323
|
defaultValue: defaultRelativePath,
|
|
284
324
|
});
|
|
@@ -299,54 +339,25 @@ export async function runInit(options = {}) {
|
|
|
299
339
|
let includeCiWorkflow = options.includeCiWorkflow ?? false;
|
|
300
340
|
let includeCdWorkflow = options.includeCdWorkflow ?? false;
|
|
301
341
|
const shouldPromptWorkflows = !skipWorkflowPrompt && options.includeCiWorkflow === undefined;
|
|
302
|
-
const shouldPromptProvider = !skipWorkflowPrompt && !workflowProvider;
|
|
303
|
-
if (shouldPromptProvider && shouldPromptWorkflows) {
|
|
304
|
-
const providerChoice = await p.select({
|
|
305
|
-
message: "Which git provider are you using?",
|
|
306
|
-
options: [
|
|
307
|
-
{ value: "github", label: "GitHub" },
|
|
308
|
-
{ value: "gitlab", label: "GitLab" },
|
|
309
|
-
],
|
|
310
|
-
});
|
|
311
|
-
if (p.isCancel(providerChoice)) {
|
|
312
|
-
p.cancel("Operation cancelled");
|
|
313
|
-
return {
|
|
314
|
-
success: false,
|
|
315
|
-
created: [],
|
|
316
|
-
skipped: [],
|
|
317
|
-
error: "Cancelled by user",
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
didPrompt = true;
|
|
321
|
-
workflowProvider = providerChoice;
|
|
322
|
-
}
|
|
323
342
|
if (shouldPromptWorkflows) {
|
|
324
|
-
const
|
|
325
|
-
message: "
|
|
326
|
-
initialValue: true,
|
|
327
|
-
});
|
|
328
|
-
if (p.isCancel(confirmWorkflows)) {
|
|
329
|
-
p.cancel("Operation cancelled");
|
|
330
|
-
return {
|
|
331
|
-
success: false,
|
|
332
|
-
created: [],
|
|
333
|
-
skipped: [],
|
|
334
|
-
error: "Cancelled by user",
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
didPrompt = true;
|
|
338
|
-
includeCiWorkflow = confirmWorkflows;
|
|
339
|
-
includeCdWorkflow = confirmWorkflows;
|
|
340
|
-
}
|
|
341
|
-
if (shouldPromptProvider && !shouldPromptWorkflows && !workflowProvider) {
|
|
342
|
-
const providerChoice = await p.select({
|
|
343
|
-
message: "Which git provider are you using?",
|
|
343
|
+
const ciChoice = await p.select({
|
|
344
|
+
message: "Set up CI/CD workflows?",
|
|
344
345
|
options: [
|
|
345
|
-
{
|
|
346
|
-
|
|
346
|
+
{
|
|
347
|
+
value: "github",
|
|
348
|
+
label: "GitHub Actions",
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
value: "gitlab",
|
|
352
|
+
label: "GitLab CI",
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
value: "skip",
|
|
356
|
+
label: "Skip",
|
|
357
|
+
},
|
|
347
358
|
],
|
|
348
359
|
});
|
|
349
|
-
if (p.isCancel(
|
|
360
|
+
if (p.isCancel(ciChoice)) {
|
|
350
361
|
p.cancel("Operation cancelled");
|
|
351
362
|
return {
|
|
352
363
|
success: false,
|
|
@@ -356,44 +367,57 @@ export async function runInit(options = {}) {
|
|
|
356
367
|
};
|
|
357
368
|
}
|
|
358
369
|
didPrompt = true;
|
|
359
|
-
|
|
370
|
+
if (ciChoice !== "skip") {
|
|
371
|
+
includeCiWorkflow = true;
|
|
372
|
+
includeCdWorkflow = true;
|
|
373
|
+
workflowProvider = ciChoice;
|
|
374
|
+
}
|
|
360
375
|
}
|
|
361
|
-
if ((includeCiWorkflow || includeCdWorkflow) && !workflowProvider) {
|
|
376
|
+
else if ((includeCiWorkflow || includeCdWorkflow) && !workflowProvider) {
|
|
362
377
|
workflowProvider = "github";
|
|
363
378
|
}
|
|
364
379
|
// Ask about existing datafiles if found
|
|
380
|
+
let datafileAction = "skip";
|
|
365
381
|
if (foundDatafiles.length > 0 && !options.skipDatafilePrompt) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
382
|
+
if (options.includeExistingDatafiles !== undefined) {
|
|
383
|
+
datafileAction = options.includeExistingDatafiles ? "include" : "skip";
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
didPrompt = true;
|
|
387
|
+
datafileAction = await promptForExistingDatafiles(foundDatafiles);
|
|
388
|
+
}
|
|
389
|
+
if (datafileAction === "include") {
|
|
372
390
|
existingDatafiles = foundDatafiles;
|
|
373
391
|
}
|
|
392
|
+
// Note: "codegen" option is handled after file creation
|
|
374
393
|
}
|
|
375
394
|
else if (options.includeExistingDatafiles && foundDatafiles.length > 0) {
|
|
376
395
|
existingDatafiles = foundDatafiles;
|
|
396
|
+
datafileAction = "include";
|
|
377
397
|
}
|
|
378
398
|
if (didPrompt) {
|
|
379
399
|
const devModeLabel = devMode === "local" ? "Tinybird Local" : "Branches";
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
400
|
+
let datafileSummary = "none found";
|
|
401
|
+
if (foundDatafiles.length > 0) {
|
|
402
|
+
if (datafileAction === "include") {
|
|
403
|
+
datafileSummary = `${foundDatafiles.length} included`;
|
|
404
|
+
}
|
|
405
|
+
else if (datafileAction === "codegen") {
|
|
406
|
+
datafileSummary = `${foundDatafiles.length} will generate .ts`;
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
datafileSummary = "skipped";
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
let cicdSummary = "skipped";
|
|
386
413
|
if (includeCiWorkflow || includeCdWorkflow) {
|
|
387
|
-
|
|
388
|
-
workflowProvider === "gitlab"
|
|
389
|
-
? "GitLab (.gitlab-ci.yml)"
|
|
390
|
-
: "GitHub Actions (tinybird-ci.yaml, tinybird-cd.yaml)";
|
|
414
|
+
cicdSummary = workflowProvider === "gitlab" ? "GitLab" : "GitHub";
|
|
391
415
|
}
|
|
392
416
|
const summaryLines = [
|
|
393
417
|
`Mode: ${devModeLabel}`,
|
|
394
|
-
`
|
|
418
|
+
`Folder: ${relativeTinybirdDir}/`,
|
|
395
419
|
`Existing datafiles: ${datafileSummary}`,
|
|
396
|
-
`
|
|
420
|
+
`CI/CD: ${cicdSummary}`,
|
|
397
421
|
];
|
|
398
422
|
p.note(summaryLines.join("\n"), "Installation Summary");
|
|
399
423
|
const confirmInit = await p.confirm({
|
|
@@ -410,15 +434,28 @@ export async function runInit(options = {}) {
|
|
|
410
434
|
};
|
|
411
435
|
}
|
|
412
436
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
const endpointsPath = path.join(tinybirdDir, "endpoints.ts");
|
|
417
|
-
const clientPath = path.join(tinybirdDir, "client.ts");
|
|
437
|
+
// relativeTinybirdDir is now a file path like "src/lib/tinybird.ts"
|
|
438
|
+
const tinybirdFilePath = path.join(cwd, relativeTinybirdDir);
|
|
439
|
+
const tinybirdDir = path.dirname(tinybirdFilePath);
|
|
418
440
|
// Create config file (tinybird.json)
|
|
419
441
|
const configPath = getConfigPath(cwd);
|
|
420
442
|
if (fs.existsSync(configPath) && !force) {
|
|
421
|
-
|
|
443
|
+
try {
|
|
444
|
+
const config = createDefaultConfig(relativeTinybirdDir, devMode, existingDatafiles);
|
|
445
|
+
updateConfig(configPath, {
|
|
446
|
+
include: config.include,
|
|
447
|
+
devMode: config.devMode,
|
|
448
|
+
});
|
|
449
|
+
created.push("tinybird.json (updated)");
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
return {
|
|
453
|
+
success: false,
|
|
454
|
+
created,
|
|
455
|
+
skipped,
|
|
456
|
+
error: `Failed to update tinybird.json: ${error.message}`,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
422
459
|
}
|
|
423
460
|
else {
|
|
424
461
|
try {
|
|
@@ -435,7 +472,7 @@ export async function runInit(options = {}) {
|
|
|
435
472
|
};
|
|
436
473
|
}
|
|
437
474
|
}
|
|
438
|
-
// Create
|
|
475
|
+
// Create lib directory
|
|
439
476
|
try {
|
|
440
477
|
fs.mkdirSync(tinybirdDir, { recursive: true });
|
|
441
478
|
}
|
|
@@ -444,61 +481,27 @@ export async function runInit(options = {}) {
|
|
|
444
481
|
success: false,
|
|
445
482
|
created,
|
|
446
483
|
skipped,
|
|
447
|
-
error: `Failed to create ${relativeTinybirdDir} folder: ${error.message}`,
|
|
484
|
+
error: `Failed to create ${path.dirname(relativeTinybirdDir)} folder: ${error.message}`,
|
|
448
485
|
};
|
|
449
486
|
}
|
|
450
|
-
// Create
|
|
451
|
-
if (
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
else {
|
|
455
|
-
try {
|
|
456
|
-
fs.writeFileSync(datasourcesPath, DATASOURCES_CONTENT);
|
|
457
|
-
created.push(`${relativeTinybirdDir}/datasources.ts`);
|
|
458
|
-
}
|
|
459
|
-
catch (error) {
|
|
460
|
-
return {
|
|
461
|
-
success: false,
|
|
462
|
-
created,
|
|
463
|
-
skipped,
|
|
464
|
-
error: `Failed to create datasources.ts: ${error.message}`,
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
// Create endpoints.ts
|
|
469
|
-
if (fs.existsSync(endpointsPath) && !force) {
|
|
470
|
-
skipped.push(`${relativeTinybirdDir}/endpoints.ts`);
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
try {
|
|
474
|
-
fs.writeFileSync(endpointsPath, ENDPOINTS_CONTENT);
|
|
475
|
-
created.push(`${relativeTinybirdDir}/endpoints.ts`);
|
|
476
|
-
}
|
|
477
|
-
catch (error) {
|
|
478
|
-
return {
|
|
479
|
-
success: false,
|
|
480
|
-
created,
|
|
481
|
-
skipped,
|
|
482
|
-
error: `Failed to create endpoints.ts: ${error.message}`,
|
|
483
|
-
};
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
// Create client.ts
|
|
487
|
-
if (fs.existsSync(clientPath) && !force) {
|
|
488
|
-
skipped.push(`${relativeTinybirdDir}/client.ts`);
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
try {
|
|
492
|
-
fs.writeFileSync(clientPath, CLIENT_CONTENT);
|
|
493
|
-
created.push(`${relativeTinybirdDir}/client.ts`);
|
|
487
|
+
// Create tinybird.ts (skip if codegen will generate it)
|
|
488
|
+
if (datafileAction !== "codegen") {
|
|
489
|
+
if (fs.existsSync(tinybirdFilePath) && !force) {
|
|
490
|
+
skipped.push(relativeTinybirdDir);
|
|
494
491
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
created
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
492
|
+
else {
|
|
493
|
+
try {
|
|
494
|
+
fs.writeFileSync(tinybirdFilePath, TINYBIRD_CONTENT);
|
|
495
|
+
created.push(relativeTinybirdDir);
|
|
496
|
+
}
|
|
497
|
+
catch (error) {
|
|
498
|
+
return {
|
|
499
|
+
success: false,
|
|
500
|
+
created,
|
|
501
|
+
skipped,
|
|
502
|
+
error: `Failed to create ${relativeTinybirdDir}: ${error.message}`,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
502
505
|
}
|
|
503
506
|
}
|
|
504
507
|
// Add scripts to package.json if it exists
|
|
@@ -531,55 +534,79 @@ export async function runInit(options = {}) {
|
|
|
531
534
|
// Silently ignore package.json errors - not critical
|
|
532
535
|
}
|
|
533
536
|
}
|
|
534
|
-
|
|
535
|
-
const
|
|
536
|
-
const
|
|
537
|
-
const
|
|
537
|
+
// Use git root for workflow files, fallback to cwd if not in a git repo
|
|
538
|
+
const projectRoot = getGitRoot() ?? cwd;
|
|
539
|
+
const githubWorkflowsDir = path.join(projectRoot, ".github", "workflows");
|
|
540
|
+
const gitlabWorkflowsDir = path.join(projectRoot, ".gitlab");
|
|
541
|
+
const githubCiPath = path.join(githubWorkflowsDir, "tinybird-ci.yaml");
|
|
542
|
+
const githubCdPath = path.join(githubWorkflowsDir, "tinybird-cd.yaml");
|
|
543
|
+
const gitlabCiPath = path.join(gitlabWorkflowsDir, "tinybird-ci.yaml");
|
|
544
|
+
const gitlabCdPath = path.join(gitlabWorkflowsDir, "tinybird-cd.yaml");
|
|
538
545
|
if (includeCiWorkflow || includeCdWorkflow) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
546
|
+
const workflowsDir = workflowProvider === "github" ? githubWorkflowsDir : gitlabWorkflowsDir;
|
|
547
|
+
try {
|
|
548
|
+
fs.mkdirSync(workflowsDir, { recursive: true });
|
|
549
|
+
}
|
|
550
|
+
catch (error) {
|
|
551
|
+
return {
|
|
552
|
+
success: false,
|
|
553
|
+
created,
|
|
554
|
+
skipped,
|
|
555
|
+
error: `Failed to create ${workflowProvider === "github" ? ".github/workflows" : ".gitlab"} folder: ${error.message}`,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (workflowProvider === "github") {
|
|
560
|
+
if (includeCiWorkflow) {
|
|
561
|
+
if (fs.existsSync(githubCiPath) && !force) {
|
|
562
|
+
skipped.push(".github/workflows/tinybird-ci.yaml");
|
|
542
563
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
created
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
564
|
+
else {
|
|
565
|
+
try {
|
|
566
|
+
fs.writeFileSync(githubCiPath, TINYBIRD_CI_WORKFLOW);
|
|
567
|
+
created.push(".github/workflows/tinybird-ci.yaml");
|
|
568
|
+
ciWorkflowCreated = true;
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
return {
|
|
572
|
+
success: false,
|
|
573
|
+
created,
|
|
574
|
+
skipped,
|
|
575
|
+
error: `Failed to create .github/workflows/tinybird-ci.yaml: ${error.message}`,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
550
578
|
}
|
|
551
579
|
}
|
|
552
|
-
if (
|
|
553
|
-
if (fs.existsSync(
|
|
554
|
-
skipped.push(".
|
|
580
|
+
if (includeCdWorkflow) {
|
|
581
|
+
if (fs.existsSync(githubCdPath) && !force) {
|
|
582
|
+
skipped.push(".github/workflows/tinybird-cd.yaml");
|
|
555
583
|
}
|
|
556
584
|
else {
|
|
557
585
|
try {
|
|
558
|
-
fs.writeFileSync(
|
|
559
|
-
created.push(".
|
|
560
|
-
|
|
561
|
-
cdWorkflowCreated = includeCdWorkflow;
|
|
586
|
+
fs.writeFileSync(githubCdPath, TINYBIRD_CD_WORKFLOW);
|
|
587
|
+
created.push(".github/workflows/tinybird-cd.yaml");
|
|
588
|
+
cdWorkflowCreated = true;
|
|
562
589
|
}
|
|
563
590
|
catch (error) {
|
|
564
591
|
return {
|
|
565
592
|
success: false,
|
|
566
593
|
created,
|
|
567
594
|
skipped,
|
|
568
|
-
error: `Failed to create .
|
|
595
|
+
error: `Failed to create .github/workflows/tinybird-cd.yaml: ${error.message}`,
|
|
569
596
|
};
|
|
570
597
|
}
|
|
571
598
|
}
|
|
572
599
|
}
|
|
573
600
|
}
|
|
574
|
-
if (workflowProvider === "
|
|
601
|
+
if (workflowProvider === "gitlab") {
|
|
575
602
|
if (includeCiWorkflow) {
|
|
576
|
-
if (fs.existsSync(
|
|
577
|
-
skipped.push(".
|
|
603
|
+
if (fs.existsSync(gitlabCiPath) && !force) {
|
|
604
|
+
skipped.push(".gitlab/tinybird-ci.yaml");
|
|
578
605
|
}
|
|
579
606
|
else {
|
|
580
607
|
try {
|
|
581
|
-
fs.writeFileSync(
|
|
582
|
-
created.push(".
|
|
608
|
+
fs.writeFileSync(gitlabCiPath, TINYBIRD_GITLAB_CI_WORKFLOW);
|
|
609
|
+
created.push(".gitlab/tinybird-ci.yaml");
|
|
583
610
|
ciWorkflowCreated = true;
|
|
584
611
|
}
|
|
585
612
|
catch (error) {
|
|
@@ -587,19 +614,19 @@ export async function runInit(options = {}) {
|
|
|
587
614
|
success: false,
|
|
588
615
|
created,
|
|
589
616
|
skipped,
|
|
590
|
-
error: `Failed to create tinybird-ci.yaml: ${error.message}`,
|
|
617
|
+
error: `Failed to create .gitlab/tinybird-ci.yaml: ${error.message}`,
|
|
591
618
|
};
|
|
592
619
|
}
|
|
593
620
|
}
|
|
594
621
|
}
|
|
595
622
|
if (includeCdWorkflow) {
|
|
596
|
-
if (fs.existsSync(
|
|
597
|
-
skipped.push(".
|
|
623
|
+
if (fs.existsSync(gitlabCdPath) && !force) {
|
|
624
|
+
skipped.push(".gitlab/tinybird-cd.yaml");
|
|
598
625
|
}
|
|
599
626
|
else {
|
|
600
627
|
try {
|
|
601
|
-
fs.writeFileSync(
|
|
602
|
-
created.push(".
|
|
628
|
+
fs.writeFileSync(gitlabCdPath, TINYBIRD_GITLAB_CD_WORKFLOW);
|
|
629
|
+
created.push(".gitlab/tinybird-cd.yaml");
|
|
603
630
|
cdWorkflowCreated = true;
|
|
604
631
|
}
|
|
605
632
|
catch (error) {
|
|
@@ -607,7 +634,7 @@ export async function runInit(options = {}) {
|
|
|
607
634
|
success: false,
|
|
608
635
|
created,
|
|
609
636
|
skipped,
|
|
610
|
-
error: `Failed to create tinybird-cd.yaml: ${error.message}`,
|
|
637
|
+
error: `Failed to create .gitlab/tinybird-cd.yaml: ${error.message}`,
|
|
611
638
|
};
|
|
612
639
|
}
|
|
613
640
|
}
|
|
@@ -629,6 +656,11 @@ export async function runInit(options = {}) {
|
|
|
629
656
|
if (baseUrl !== "https://api.tinybird.co") {
|
|
630
657
|
updateConfig(configPath, { baseUrl });
|
|
631
658
|
}
|
|
659
|
+
// Generate TypeScript from existing Tinybird resources if requested
|
|
660
|
+
if (datafileAction === "codegen") {
|
|
661
|
+
const tinybirdDir = path.join(cwd, relativeTinybirdDir);
|
|
662
|
+
await runCodegen(baseUrl, authResult.token, tinybirdDir, relativeTinybirdDir, created, foundDatafiles);
|
|
663
|
+
}
|
|
632
664
|
return {
|
|
633
665
|
success: true,
|
|
634
666
|
created,
|
|
@@ -677,6 +709,21 @@ export async function runInit(options = {}) {
|
|
|
677
709
|
};
|
|
678
710
|
}
|
|
679
711
|
}
|
|
712
|
+
// Generate TypeScript from existing Tinybird resources if requested
|
|
713
|
+
// (when user is already logged in)
|
|
714
|
+
if (datafileAction === "codegen" && hasValidToken(cwd)) {
|
|
715
|
+
try {
|
|
716
|
+
const config = loadConfig(cwd);
|
|
717
|
+
const tinybirdDir = path.join(cwd, relativeTinybirdDir);
|
|
718
|
+
await runCodegen(config.baseUrl, config.token, tinybirdDir, relativeTinybirdDir, created, foundDatafiles);
|
|
719
|
+
}
|
|
720
|
+
catch (error) {
|
|
721
|
+
console.error(`Warning: Failed to generate TypeScript: ${error.message}`);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (didPrompt) {
|
|
725
|
+
p.outro("Done!");
|
|
726
|
+
}
|
|
680
727
|
return {
|
|
681
728
|
success: true,
|
|
682
729
|
created,
|
|
@@ -689,6 +736,39 @@ export async function runInit(options = {}) {
|
|
|
689
736
|
workflowProvider,
|
|
690
737
|
};
|
|
691
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* Generate TypeScript files from Tinybird workspace resources
|
|
741
|
+
* Only generates for resources that match the local datafiles
|
|
742
|
+
*/
|
|
743
|
+
async function runCodegen(baseUrl, token, tinybirdFilePath, relativeTinybirdPath, created, localDatafiles) {
|
|
744
|
+
try {
|
|
745
|
+
// Extract names from local datafiles (without extension)
|
|
746
|
+
const localDatasourceNames = new Set(localDatafiles
|
|
747
|
+
.filter((f) => f.endsWith(".datasource"))
|
|
748
|
+
.map((f) => path.basename(f, ".datasource")));
|
|
749
|
+
const localPipeNames = new Set(localDatafiles
|
|
750
|
+
.filter((f) => f.endsWith(".pipe"))
|
|
751
|
+
.map((f) => path.basename(f, ".pipe")));
|
|
752
|
+
const resources = await fetchAllResources({ baseUrl, token });
|
|
753
|
+
// Filter to only resources matching local files
|
|
754
|
+
const matchedDatasources = resources.datasources.filter((ds) => localDatasourceNames.has(ds.name));
|
|
755
|
+
const matchedPipes = resources.pipes.filter((p) => localPipeNames.has(p.name));
|
|
756
|
+
if (matchedDatasources.length > 0 || matchedPipes.length > 0) {
|
|
757
|
+
// Generate combined tinybird.ts file
|
|
758
|
+
const content = generateCombinedFile(matchedDatasources, matchedPipes);
|
|
759
|
+
// Ensure directory exists
|
|
760
|
+
const dir = path.dirname(tinybirdFilePath);
|
|
761
|
+
if (!fs.existsSync(dir)) {
|
|
762
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
763
|
+
}
|
|
764
|
+
fs.writeFileSync(tinybirdFilePath, content);
|
|
765
|
+
created.push(`${relativeTinybirdPath} (generated)`);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
catch (error) {
|
|
769
|
+
console.error(`Warning: Failed to generate TypeScript from workspace: ${error.message}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
692
772
|
/**
|
|
693
773
|
* Prompt user about including existing datafiles
|
|
694
774
|
*/
|
|
@@ -702,13 +782,29 @@ async function promptForExistingDatafiles(datafiles) {
|
|
|
702
782
|
if (pipeCount > 0) {
|
|
703
783
|
parts.push(`${pipeCount} .pipe file${pipeCount > 1 ? "s" : ""}`);
|
|
704
784
|
}
|
|
705
|
-
const
|
|
706
|
-
message: `Found ${parts.join(" and ")} in your project
|
|
707
|
-
|
|
785
|
+
const choice = await p.select({
|
|
786
|
+
message: `Found ${parts.join(" and ")} in your project.`,
|
|
787
|
+
options: [
|
|
788
|
+
{
|
|
789
|
+
value: "include",
|
|
790
|
+
label: "Include existing resources",
|
|
791
|
+
hint: "Add to tinybird.json",
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
value: "codegen",
|
|
795
|
+
label: "Define resources in TypeScript",
|
|
796
|
+
hint: "Generate TypeScript definitions from existing resources",
|
|
797
|
+
},
|
|
798
|
+
{
|
|
799
|
+
value: "skip",
|
|
800
|
+
label: "Skip",
|
|
801
|
+
hint: "Don't include existing resources",
|
|
802
|
+
},
|
|
803
|
+
],
|
|
708
804
|
});
|
|
709
|
-
if (p.isCancel(
|
|
710
|
-
return
|
|
805
|
+
if (p.isCancel(choice)) {
|
|
806
|
+
return "skip";
|
|
711
807
|
}
|
|
712
|
-
return
|
|
808
|
+
return choice;
|
|
713
809
|
}
|
|
714
810
|
//# sourceMappingURL=init.js.map
|