@tinybirdco/sdk 0.0.20 → 0.0.21
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/dashboard.d.ts +74 -0
- package/dist/api/dashboard.d.ts.map +1 -0
- package/dist/api/dashboard.js +102 -0
- package/dist/api/dashboard.js.map +1 -0
- package/dist/api/dashboard.test.d.ts +2 -0
- package/dist/api/dashboard.test.d.ts.map +1 -0
- package/dist/api/dashboard.test.js +91 -0
- package/dist/api/dashboard.test.js.map +1 -0
- package/dist/cli/commands/branch.d.ts +2 -0
- package/dist/cli/commands/branch.d.ts.map +1 -1
- package/dist/cli/commands/branch.js +12 -1
- package/dist/cli/commands/branch.js.map +1 -1
- package/dist/cli/commands/build.d.ts +17 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +25 -0
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/dev.d.ts +2 -0
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +19 -3
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/index.js +23 -24
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +20 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +37 -0
- package/dist/cli/output.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/dashboard.test.ts +115 -0
- package/src/api/dashboard.ts +121 -0
- package/src/cli/commands/branch.ts +15 -1
- package/src/cli/commands/build.ts +46 -0
- package/src/cli/commands/dev.ts +47 -7
- package/src/cli/index.ts +25 -27
- package/src/cli/output.ts +54 -0
- package/src/index.ts +9 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tinybird Dashboard URL utilities
|
|
3
|
+
*
|
|
4
|
+
* Generates dashboard links for workspaces and branches
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Region information extracted from API URL
|
|
9
|
+
*/
|
|
10
|
+
export interface RegionInfo {
|
|
11
|
+
/** Cloud provider: "gcp" or "aws" */
|
|
12
|
+
provider: string;
|
|
13
|
+
/** Region identifier (e.g., "europe-west3", "us-east4", "us-west-2") */
|
|
14
|
+
region: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Mapping of API hostnames to region information
|
|
19
|
+
*
|
|
20
|
+
* Based on https://www.tinybird.co/docs/api-reference#current-tinybird-regions
|
|
21
|
+
*/
|
|
22
|
+
const API_REGION_MAP: Record<string, RegionInfo> = {
|
|
23
|
+
// GCP Regions
|
|
24
|
+
"api.tinybird.co": { provider: "gcp", region: "europe-west3" },
|
|
25
|
+
"api.us-east.tinybird.co": { provider: "gcp", region: "us-east4" },
|
|
26
|
+
// AWS Regions
|
|
27
|
+
"api.eu-central-1.aws.tinybird.co": { provider: "aws", region: "eu-central-1" },
|
|
28
|
+
"api.us-east-1.aws.tinybird.co": { provider: "aws", region: "us-east-1" },
|
|
29
|
+
"api.us-west-2.aws.tinybird.co": { provider: "aws", region: "us-west-2" },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parse an API URL to extract region information
|
|
34
|
+
*
|
|
35
|
+
* @param apiUrl - The Tinybird API base URL (e.g., "https://api.tinybird.co")
|
|
36
|
+
* @returns Region info or null if the URL doesn't match a known region
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* parseApiUrl("https://api.tinybird.co")
|
|
41
|
+
* // => { provider: "gcp", region: "europe-west3" }
|
|
42
|
+
*
|
|
43
|
+
* parseApiUrl("https://api.us-west-2.aws.tinybird.co")
|
|
44
|
+
* // => { provider: "aws", region: "us-west-2" }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function parseApiUrl(apiUrl: string): RegionInfo | null {
|
|
48
|
+
try {
|
|
49
|
+
const url = new URL(apiUrl);
|
|
50
|
+
const hostname = url.hostname;
|
|
51
|
+
return API_REGION_MAP[hostname] ?? null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Generate a Tinybird dashboard URL for a workspace
|
|
59
|
+
*
|
|
60
|
+
* @param apiUrl - The Tinybird API base URL
|
|
61
|
+
* @param workspaceName - The workspace name
|
|
62
|
+
* @returns Dashboard URL or null if the API URL is not recognized
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* getDashboardUrl("https://api.tinybird.co", "my_workspace")
|
|
67
|
+
* // => "https://cloud.tinybird.co/gcp/europe-west3/my_workspace"
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export function getDashboardUrl(apiUrl: string, workspaceName: string): string | null {
|
|
71
|
+
const regionInfo = parseApiUrl(apiUrl);
|
|
72
|
+
if (!regionInfo) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return `https://cloud.tinybird.co/${regionInfo.provider}/${regionInfo.region}/${workspaceName}`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Generate a Tinybird dashboard URL for a branch
|
|
81
|
+
*
|
|
82
|
+
* @param apiUrl - The Tinybird API base URL
|
|
83
|
+
* @param workspaceName - The workspace name
|
|
84
|
+
* @param branchName - The branch name
|
|
85
|
+
* @returns Dashboard URL or null if the API URL is not recognized
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* getBranchDashboardUrl("https://api.tinybird.co", "my_workspace", "feature_branch")
|
|
90
|
+
* // => "https://cloud.tinybird.co/gcp/europe-west3/my_workspace~feature_branch"
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function getBranchDashboardUrl(
|
|
94
|
+
apiUrl: string,
|
|
95
|
+
workspaceName: string,
|
|
96
|
+
branchName: string
|
|
97
|
+
): string | null {
|
|
98
|
+
const regionInfo = parseApiUrl(apiUrl);
|
|
99
|
+
if (!regionInfo) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return `https://cloud.tinybird.co/${regionInfo.provider}/${regionInfo.region}/${workspaceName}~${branchName}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Generate a local Tinybird dashboard URL
|
|
108
|
+
*
|
|
109
|
+
* @param workspaceName - The local workspace name
|
|
110
|
+
* @param port - The local Tinybird port (default: 7181)
|
|
111
|
+
* @returns Local dashboard URL
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```ts
|
|
115
|
+
* getLocalDashboardUrl("my_local_workspace")
|
|
116
|
+
* // => "https://cloud.tinybird.co/local/7181/my_local_workspace"
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export function getLocalDashboardUrl(workspaceName: string, port = 7181): string {
|
|
120
|
+
return `https://cloud.tinybird.co/local/${port}/${workspaceName}`;
|
|
121
|
+
}
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
removeBranch as removeCachedBranch,
|
|
17
17
|
listCachedBranches,
|
|
18
18
|
} from "../branch-store.js";
|
|
19
|
+
import { getBranchDashboardUrl } from "../../api/dashboard.js";
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Branch command options
|
|
@@ -53,6 +54,8 @@ export interface BranchStatusResult {
|
|
|
53
54
|
tinybirdBranch?: TinybirdBranch;
|
|
54
55
|
/** Whether a cached token exists */
|
|
55
56
|
hasCachedToken: boolean;
|
|
57
|
+
/** Dashboard URL for the branch */
|
|
58
|
+
dashboardUrl?: string;
|
|
56
59
|
/** Error message if failed */
|
|
57
60
|
error?: string;
|
|
58
61
|
}
|
|
@@ -135,14 +138,16 @@ export async function runBranchStatus(
|
|
|
135
138
|
const tinybirdBranchName = config.tinybirdBranch; // Sanitized name
|
|
136
139
|
const isMainBranch = config.isMainBranch;
|
|
137
140
|
|
|
138
|
-
// Fetch the workspace
|
|
141
|
+
// Fetch the workspace from the API
|
|
139
142
|
let workspaceId: string;
|
|
143
|
+
let workspaceName: string;
|
|
140
144
|
try {
|
|
141
145
|
const workspace = await getWorkspace({
|
|
142
146
|
baseUrl: config.baseUrl,
|
|
143
147
|
token: config.token,
|
|
144
148
|
});
|
|
145
149
|
workspaceId = workspace.id;
|
|
150
|
+
workspaceName = workspace.name;
|
|
146
151
|
} catch (error) {
|
|
147
152
|
return {
|
|
148
153
|
success: false,
|
|
@@ -154,6 +159,11 @@ export async function runBranchStatus(
|
|
|
154
159
|
};
|
|
155
160
|
}
|
|
156
161
|
|
|
162
|
+
// Generate dashboard URL for the branch
|
|
163
|
+
const dashboardUrl = tinybirdBranchName
|
|
164
|
+
? getBranchDashboardUrl(config.baseUrl, workspaceName, tinybirdBranchName) ?? undefined
|
|
165
|
+
: undefined;
|
|
166
|
+
|
|
157
167
|
// Check for cached token (use sanitized name)
|
|
158
168
|
const cachedBranch = tinybirdBranchName ? getBranchToken(workspaceId, tinybirdBranchName) : null;
|
|
159
169
|
const hasCachedToken = cachedBranch !== null;
|
|
@@ -166,6 +176,7 @@ export async function runBranchStatus(
|
|
|
166
176
|
tinybirdBranchName,
|
|
167
177
|
isMainBranch,
|
|
168
178
|
hasCachedToken,
|
|
179
|
+
dashboardUrl,
|
|
169
180
|
};
|
|
170
181
|
}
|
|
171
182
|
|
|
@@ -186,6 +197,7 @@ export async function runBranchStatus(
|
|
|
186
197
|
isMainBranch,
|
|
187
198
|
tinybirdBranch,
|
|
188
199
|
hasCachedToken,
|
|
200
|
+
dashboardUrl,
|
|
189
201
|
};
|
|
190
202
|
} catch (error) {
|
|
191
203
|
// If 404, branch doesn't exist yet
|
|
@@ -196,6 +208,7 @@ export async function runBranchStatus(
|
|
|
196
208
|
tinybirdBranchName,
|
|
197
209
|
isMainBranch,
|
|
198
210
|
hasCachedToken,
|
|
211
|
+
dashboardUrl,
|
|
199
212
|
};
|
|
200
213
|
}
|
|
201
214
|
|
|
@@ -205,6 +218,7 @@ export async function runBranchStatus(
|
|
|
205
218
|
tinybirdBranchName,
|
|
206
219
|
isMainBranch,
|
|
207
220
|
hasCachedToken,
|
|
221
|
+
dashboardUrl,
|
|
208
222
|
error: (error as Error).message,
|
|
209
223
|
};
|
|
210
224
|
}
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
getLocalWorkspaceName,
|
|
13
13
|
LocalNotRunningError,
|
|
14
14
|
} from "../../api/local.js";
|
|
15
|
+
import { getWorkspace } from "../../api/workspaces.js";
|
|
16
|
+
import { getBranchDashboardUrl, getLocalDashboardUrl } from "../../api/dashboard.js";
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Build command options
|
|
@@ -27,6 +29,22 @@ export interface BuildCommandOptions {
|
|
|
27
29
|
devModeOverride?: DevMode;
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Branch info included in build result
|
|
34
|
+
*/
|
|
35
|
+
export interface BuildBranchInfo {
|
|
36
|
+
/** Git branch name */
|
|
37
|
+
gitBranch: string | null;
|
|
38
|
+
/** Tinybird branch name */
|
|
39
|
+
tinybirdBranch: string | null;
|
|
40
|
+
/** Whether the branch was newly created */
|
|
41
|
+
wasCreated: boolean;
|
|
42
|
+
/** Dashboard URL for the branch */
|
|
43
|
+
dashboardUrl?: string;
|
|
44
|
+
/** Whether using local mode */
|
|
45
|
+
isLocal: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
30
48
|
/**
|
|
31
49
|
* Build command result
|
|
32
50
|
*/
|
|
@@ -37,6 +55,8 @@ export interface BuildCommandResult {
|
|
|
37
55
|
build?: BuildFromIncludeResult;
|
|
38
56
|
/** Build API result (if not dry run) */
|
|
39
57
|
deploy?: BuildApiResult;
|
|
58
|
+
/** Branch info (when building to a branch) */
|
|
59
|
+
branchInfo?: BuildBranchInfo;
|
|
40
60
|
/** Error message if failed */
|
|
41
61
|
error?: string;
|
|
42
62
|
/** Duration in milliseconds */
|
|
@@ -101,6 +121,7 @@ export async function runBuild(options: BuildCommandOptions = {}): Promise<Build
|
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
let deployResult: BuildApiResult;
|
|
124
|
+
let branchInfo: BuildBranchInfo | undefined;
|
|
104
125
|
|
|
105
126
|
// Handle local mode
|
|
106
127
|
if (devMode === "local") {
|
|
@@ -123,6 +144,14 @@ export async function runBuild(options: BuildCommandOptions = {}): Promise<Build
|
|
|
123
144
|
console.log(`[debug] Workspace ${wasCreated ? "created" : "found"}: ${workspace.name}`);
|
|
124
145
|
}
|
|
125
146
|
|
|
147
|
+
branchInfo = {
|
|
148
|
+
gitBranch: config.gitBranch,
|
|
149
|
+
tinybirdBranch: workspaceName,
|
|
150
|
+
wasCreated,
|
|
151
|
+
dashboardUrl: getLocalDashboardUrl(workspaceName),
|
|
152
|
+
isLocal: true,
|
|
153
|
+
};
|
|
154
|
+
|
|
126
155
|
// Always use /v1/build for local (no deploy endpoint)
|
|
127
156
|
deployResult = await buildToTinybird(
|
|
128
157
|
{
|
|
@@ -197,6 +226,21 @@ export async function runBuild(options: BuildCommandOptions = {}): Promise<Build
|
|
|
197
226
|
if (debug) {
|
|
198
227
|
console.log(`[debug] Using branch token for branch: ${config.tinybirdBranch}`);
|
|
199
228
|
}
|
|
229
|
+
|
|
230
|
+
// Get workspace name for dashboard URL
|
|
231
|
+
const workspace = await getWorkspace({
|
|
232
|
+
baseUrl: config.baseUrl,
|
|
233
|
+
token: config.token,
|
|
234
|
+
});
|
|
235
|
+
const dashboardUrl = getBranchDashboardUrl(config.baseUrl, workspace.name, config.tinybirdBranch!) ?? undefined;
|
|
236
|
+
|
|
237
|
+
branchInfo = {
|
|
238
|
+
gitBranch: config.gitBranch,
|
|
239
|
+
tinybirdBranch: config.tinybirdBranch,
|
|
240
|
+
wasCreated: tinybirdBranch.wasCreated ?? false,
|
|
241
|
+
dashboardUrl,
|
|
242
|
+
isLocal: false,
|
|
243
|
+
};
|
|
200
244
|
} catch (error) {
|
|
201
245
|
return {
|
|
202
246
|
success: false,
|
|
@@ -231,6 +275,7 @@ export async function runBuild(options: BuildCommandOptions = {}): Promise<Build
|
|
|
231
275
|
success: false,
|
|
232
276
|
build: buildResult,
|
|
233
277
|
deploy: deployResult,
|
|
278
|
+
branchInfo,
|
|
234
279
|
error: deployResult.error,
|
|
235
280
|
durationMs: Date.now() - startTime,
|
|
236
281
|
};
|
|
@@ -240,6 +285,7 @@ export async function runBuild(options: BuildCommandOptions = {}): Promise<Build
|
|
|
240
285
|
success: true,
|
|
241
286
|
build: buildResult,
|
|
242
287
|
deploy: deployResult,
|
|
288
|
+
branchInfo,
|
|
243
289
|
durationMs: Date.now() - startTime,
|
|
244
290
|
};
|
|
245
291
|
}
|
package/src/cli/commands/dev.ts
CHANGED
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import { watch } from "chokidar";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
loadConfig,
|
|
9
|
+
configExists,
|
|
10
|
+
findConfigFile,
|
|
11
|
+
hasValidToken,
|
|
12
|
+
updateConfig,
|
|
13
|
+
LOCAL_BASE_URL,
|
|
14
|
+
type ResolvedConfig,
|
|
15
|
+
type DevMode,
|
|
16
|
+
} from "../config.js";
|
|
8
17
|
import { runBuild, type BuildCommandResult } from "./build.js";
|
|
9
18
|
import { getOrCreateBranch, type TinybirdBranch } from "../../api/branches.js";
|
|
10
19
|
import { browserLogin } from "../auth.js";
|
|
@@ -19,6 +28,8 @@ import {
|
|
|
19
28
|
getLocalWorkspaceName,
|
|
20
29
|
type LocalWorkspace,
|
|
21
30
|
} from "../../api/local.js";
|
|
31
|
+
import { getWorkspace } from "../../api/workspaces.js";
|
|
32
|
+
import { getBranchDashboardUrl, getLocalDashboardUrl } from "../../api/dashboard.js";
|
|
22
33
|
|
|
23
34
|
/**
|
|
24
35
|
* Login result info
|
|
@@ -70,6 +81,8 @@ export interface BranchReadyInfo {
|
|
|
70
81
|
isLocal?: boolean;
|
|
71
82
|
/** Local workspace info (only in local mode) */
|
|
72
83
|
localWorkspace?: LocalWorkspace;
|
|
84
|
+
/** Dashboard URL for the branch (only in branch mode) */
|
|
85
|
+
dashboardUrl?: string;
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
/**
|
|
@@ -99,7 +112,9 @@ export interface DevController {
|
|
|
99
112
|
* @param options - Dev options
|
|
100
113
|
* @returns Dev controller
|
|
101
114
|
*/
|
|
102
|
-
export async function runDev(
|
|
115
|
+
export async function runDev(
|
|
116
|
+
options: DevCommandOptions = {}
|
|
117
|
+
): Promise<DevController> {
|
|
103
118
|
const cwd = options.cwd ?? process.cwd();
|
|
104
119
|
const debounceMs = options.debounce ?? 100;
|
|
105
120
|
|
|
@@ -129,7 +144,8 @@ export async function runDev(options: DevCommandOptions = {}): Promise<DevContro
|
|
|
129
144
|
|
|
130
145
|
if (!authResult.success || !authResult.token) {
|
|
131
146
|
throw new Error(
|
|
132
|
-
authResult.error ??
|
|
147
|
+
authResult.error ??
|
|
148
|
+
"Login failed. Run 'npx tinybird login' to authenticate."
|
|
133
149
|
);
|
|
134
150
|
}
|
|
135
151
|
|
|
@@ -173,8 +189,14 @@ export async function runDev(options: DevCommandOptions = {}): Promise<DevContro
|
|
|
173
189
|
if (devMode === "local") {
|
|
174
190
|
// Local mode: get tokens from local container and set up workspace
|
|
175
191
|
const localTokens = await getLocalTokens();
|
|
176
|
-
const workspaceName = getLocalWorkspaceName(
|
|
177
|
-
|
|
192
|
+
const workspaceName = getLocalWorkspaceName(
|
|
193
|
+
config.tinybirdBranch,
|
|
194
|
+
config.cwd
|
|
195
|
+
);
|
|
196
|
+
const { workspace, wasCreated } = await getOrCreateLocalWorkspace(
|
|
197
|
+
localTokens,
|
|
198
|
+
workspaceName
|
|
199
|
+
);
|
|
178
200
|
|
|
179
201
|
effectiveToken = workspace.token;
|
|
180
202
|
effectiveBaseUrl = LOCAL_BASE_URL;
|
|
@@ -184,6 +206,7 @@ export async function runDev(options: DevCommandOptions = {}): Promise<DevContro
|
|
|
184
206
|
isLocal: true,
|
|
185
207
|
localWorkspace: workspace,
|
|
186
208
|
wasCreated,
|
|
209
|
+
dashboardUrl: getLocalDashboardUrl(workspace.name),
|
|
187
210
|
};
|
|
188
211
|
} else {
|
|
189
212
|
// Branch mode: use Tinybird cloud with branches
|
|
@@ -216,11 +239,22 @@ export async function runDev(options: DevCommandOptions = {}): Promise<DevContro
|
|
|
216
239
|
}
|
|
217
240
|
|
|
218
241
|
effectiveToken = tinybirdBranch.token;
|
|
242
|
+
|
|
243
|
+
// Get workspace name for dashboard URL
|
|
244
|
+
const workspace = await getWorkspace({
|
|
245
|
+
baseUrl: config.baseUrl,
|
|
246
|
+
token: config.token,
|
|
247
|
+
});
|
|
248
|
+
const dashboardUrl =
|
|
249
|
+
getBranchDashboardUrl(config.baseUrl, workspace.name, branchName) ??
|
|
250
|
+
undefined;
|
|
251
|
+
|
|
219
252
|
branchInfo = {
|
|
220
253
|
gitBranch: config.gitBranch, // Original git branch name for display
|
|
221
254
|
isMainBranch: false,
|
|
222
255
|
tinybirdBranch,
|
|
223
256
|
wasCreated: tinybirdBranch.wasCreated ?? false,
|
|
257
|
+
dashboardUrl,
|
|
224
258
|
};
|
|
225
259
|
}
|
|
226
260
|
}
|
|
@@ -246,7 +280,11 @@ export async function runDev(options: DevCommandOptions = {}): Promise<DevContro
|
|
|
246
280
|
async function doBuild(): Promise<BuildCommandResult> {
|
|
247
281
|
if (isBuilding) {
|
|
248
282
|
pendingBuild = true;
|
|
249
|
-
return {
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
error: "Build already in progress",
|
|
286
|
+
durationMs: 0,
|
|
287
|
+
};
|
|
250
288
|
}
|
|
251
289
|
|
|
252
290
|
isBuilding = true;
|
|
@@ -357,7 +395,9 @@ export async function runDev(options: DevCommandOptions = {}): Promise<DevContro
|
|
|
357
395
|
});
|
|
358
396
|
|
|
359
397
|
watcher.on("error", (error: unknown) => {
|
|
360
|
-
options.onError?.(
|
|
398
|
+
options.onError?.(
|
|
399
|
+
error instanceof Error ? error : new Error(String(error))
|
|
400
|
+
);
|
|
361
401
|
});
|
|
362
402
|
|
|
363
403
|
// Do initial build
|
package/src/cli/index.ts
CHANGED
|
@@ -188,15 +188,19 @@ function createCli(): Command {
|
|
|
188
188
|
devModeOverride = "local";
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
const modeLabel = devModeOverride === "local" ? " (local)" : "";
|
|
192
|
-
output.highlight(`Building${modeLabel}...`);
|
|
193
|
-
|
|
194
191
|
const result = await runBuild({
|
|
195
192
|
dryRun: options.dryRun,
|
|
196
193
|
devModeOverride,
|
|
197
194
|
});
|
|
198
195
|
|
|
199
|
-
const { build, deploy } = result;
|
|
196
|
+
const { build, deploy, branchInfo } = result;
|
|
197
|
+
|
|
198
|
+
// Show branch info
|
|
199
|
+
if (branchInfo) {
|
|
200
|
+
output.showBranchInfo(branchInfo);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
output.highlight("Building...");
|
|
200
204
|
|
|
201
205
|
if (!result.success) {
|
|
202
206
|
// Show detailed errors if available
|
|
@@ -486,32 +490,23 @@ function createCli(): Command {
|
|
|
486
490
|
},
|
|
487
491
|
onBranchReady: (info) => {
|
|
488
492
|
if (info.isLocal) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
console.log(`Using local Tinybird container`);
|
|
497
|
-
console.log(
|
|
498
|
-
`Using existing local workspace '${workspaceName}'\n`
|
|
499
|
-
);
|
|
500
|
-
}
|
|
493
|
+
output.showBranchInfo({
|
|
494
|
+
gitBranch: info.gitBranch,
|
|
495
|
+
tinybirdBranch: info.localWorkspace?.name ?? null,
|
|
496
|
+
wasCreated: info.wasCreated ?? false,
|
|
497
|
+
dashboardUrl: info.dashboardUrl,
|
|
498
|
+
isLocal: true,
|
|
499
|
+
});
|
|
501
500
|
} else if (info.isMainBranch) {
|
|
502
501
|
console.log("On main branch - deploying to workspace\n");
|
|
503
502
|
} else if (info.gitBranch) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
console.log(
|
|
512
|
-
`Using existing Tinybird branch '${tinybirdName}'\n`
|
|
513
|
-
);
|
|
514
|
-
}
|
|
503
|
+
output.showBranchInfo({
|
|
504
|
+
gitBranch: info.gitBranch,
|
|
505
|
+
tinybirdBranch: info.tinybirdBranch?.name ?? null,
|
|
506
|
+
wasCreated: info.wasCreated ?? false,
|
|
507
|
+
dashboardUrl: info.dashboardUrl,
|
|
508
|
+
isLocal: false,
|
|
509
|
+
});
|
|
515
510
|
} else {
|
|
516
511
|
console.log("Not in a git repository - deploying to workspace\n");
|
|
517
512
|
}
|
|
@@ -659,6 +654,9 @@ function createCli(): Command {
|
|
|
659
654
|
console.log(` Tinybird branch: ${result.tinybirdBranch.name}`);
|
|
660
655
|
console.log(` Branch ID: ${result.tinybirdBranch.id}`);
|
|
661
656
|
console.log(` Created: ${result.tinybirdBranch.created_at}`);
|
|
657
|
+
if (result.dashboardUrl) {
|
|
658
|
+
console.log(` Dashboard: ${result.dashboardUrl}`);
|
|
659
|
+
}
|
|
662
660
|
} else if (!result.isMainBranch && result.tinybirdBranchName) {
|
|
663
661
|
console.log(" Tinybird branch: not created yet");
|
|
664
662
|
console.log(" (Run 'npx tinybird dev' to create it)");
|
package/src/cli/output.ts
CHANGED
|
@@ -239,6 +239,59 @@ export function showDeployFailure(): void {
|
|
|
239
239
|
error(`\n✗ Deploy failed`);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Branch info for display
|
|
244
|
+
*/
|
|
245
|
+
export interface BranchDisplayInfo {
|
|
246
|
+
/** Git branch name */
|
|
247
|
+
gitBranch: string | null;
|
|
248
|
+
/** Tinybird branch name */
|
|
249
|
+
tinybirdBranch: string | null;
|
|
250
|
+
/** Whether the branch was newly created */
|
|
251
|
+
wasCreated: boolean;
|
|
252
|
+
/** Dashboard URL for the branch */
|
|
253
|
+
dashboardUrl?: string;
|
|
254
|
+
/** Whether using local mode */
|
|
255
|
+
isLocal?: boolean;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Show branch information in a compact, styled format
|
|
260
|
+
*/
|
|
261
|
+
export function showBranchInfo(info: BranchDisplayInfo): void {
|
|
262
|
+
const status = info.wasCreated
|
|
263
|
+
? colorize("✓ created", "green")
|
|
264
|
+
: colorize("existing", "gray");
|
|
265
|
+
|
|
266
|
+
if (info.isLocal) {
|
|
267
|
+
// Show git branch
|
|
268
|
+
if (info.gitBranch) {
|
|
269
|
+
console.log(`» Git branch: ${info.gitBranch}`);
|
|
270
|
+
}
|
|
271
|
+
// Show local workspace
|
|
272
|
+
const name = info.tinybirdBranch ?? "unknown";
|
|
273
|
+
console.log(`» Local workspace: ${name} ${status}`);
|
|
274
|
+
// Show dashboard URL
|
|
275
|
+
if (info.dashboardUrl) {
|
|
276
|
+
console.log(colorize(` ↳ ${info.dashboardUrl}`, "gray"));
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
// Show git branch
|
|
280
|
+
if (info.gitBranch) {
|
|
281
|
+
console.log(`» Git branch: ${info.gitBranch}`);
|
|
282
|
+
}
|
|
283
|
+
// Show Tinybird branch
|
|
284
|
+
if (info.tinybirdBranch) {
|
|
285
|
+
console.log(`» Tinybird branch: ${info.tinybirdBranch} ${status}`);
|
|
286
|
+
}
|
|
287
|
+
// Show dashboard URL
|
|
288
|
+
if (info.dashboardUrl) {
|
|
289
|
+
console.log(colorize(` ↳ ${info.dashboardUrl}`, "gray"));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
console.log("");
|
|
293
|
+
}
|
|
294
|
+
|
|
242
295
|
/**
|
|
243
296
|
* Output object containing all output functions
|
|
244
297
|
*/
|
|
@@ -265,4 +318,5 @@ export const output = {
|
|
|
265
318
|
showValidatingDeployment,
|
|
266
319
|
showDeploySuccess,
|
|
267
320
|
showDeployFailure,
|
|
321
|
+
showBranchInfo,
|
|
268
322
|
};
|
package/src/index.ts
CHANGED
|
@@ -235,3 +235,12 @@ export {
|
|
|
235
235
|
resolveToken,
|
|
236
236
|
clearTokenCache,
|
|
237
237
|
} from "./client/preview.js";
|
|
238
|
+
|
|
239
|
+
// ============ Dashboard URL Utilities ============
|
|
240
|
+
export {
|
|
241
|
+
parseApiUrl,
|
|
242
|
+
getDashboardUrl,
|
|
243
|
+
getBranchDashboardUrl,
|
|
244
|
+
getLocalDashboardUrl,
|
|
245
|
+
} from "./api/dashboard.js";
|
|
246
|
+
export type { RegionInfo } from "./api/dashboard.js";
|