@tinybirdco/sdk 0.0.41 → 0.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +29 -3
- package/dist/api/resources.d.ts +72 -1
- package/dist/api/resources.d.ts.map +1 -1
- package/dist/api/resources.js +197 -1
- package/dist/api/resources.js.map +1 -1
- package/dist/api/resources.test.js +82 -1
- package/dist/api/resources.test.js.map +1 -1
- package/dist/cli/commands/migrate.d.ts +11 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +196 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/migrate.test.d.ts +2 -0
- package/dist/cli/commands/migrate.test.d.ts.map +1 -0
- package/dist/cli/commands/migrate.test.js +473 -0
- package/dist/cli/commands/migrate.test.js.map +1 -0
- package/dist/cli/commands/pull.d.ts +59 -0
- package/dist/cli/commands/pull.d.ts.map +1 -0
- package/dist/cli/commands/pull.js +104 -0
- package/dist/cli/commands/pull.js.map +1 -0
- package/dist/cli/commands/pull.test.d.ts +2 -0
- package/dist/cli/commands/pull.test.d.ts.map +1 -0
- package/dist/cli/commands/pull.test.js +140 -0
- package/dist/cli/commands/pull.test.js.map +1 -0
- package/dist/cli/config.d.ts +10 -0
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +22 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/index.js +77 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/generator/client.js +2 -2
- package/dist/generator/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/migrate/discovery.d.ts +7 -0
- package/dist/migrate/discovery.d.ts.map +1 -0
- package/dist/migrate/discovery.js +125 -0
- package/dist/migrate/discovery.js.map +1 -0
- package/dist/migrate/emit-ts.d.ts +4 -0
- package/dist/migrate/emit-ts.d.ts.map +1 -0
- package/dist/migrate/emit-ts.js +387 -0
- package/dist/migrate/emit-ts.js.map +1 -0
- package/dist/migrate/parse-connection.d.ts +3 -0
- package/dist/migrate/parse-connection.d.ts.map +1 -0
- package/dist/migrate/parse-connection.js +74 -0
- package/dist/migrate/parse-connection.js.map +1 -0
- package/dist/migrate/parse-datasource.d.ts +3 -0
- package/dist/migrate/parse-datasource.d.ts.map +1 -0
- package/dist/migrate/parse-datasource.js +324 -0
- package/dist/migrate/parse-datasource.js.map +1 -0
- package/dist/migrate/parse-pipe.d.ts +3 -0
- package/dist/migrate/parse-pipe.d.ts.map +1 -0
- package/dist/migrate/parse-pipe.js +332 -0
- package/dist/migrate/parse-pipe.js.map +1 -0
- package/dist/migrate/parse.d.ts +3 -0
- package/dist/migrate/parse.d.ts.map +1 -0
- package/dist/migrate/parse.js +18 -0
- package/dist/migrate/parse.js.map +1 -0
- package/dist/migrate/parser-utils.d.ts +20 -0
- package/dist/migrate/parser-utils.d.ts.map +1 -0
- package/dist/migrate/parser-utils.js +130 -0
- package/dist/migrate/parser-utils.js.map +1 -0
- package/dist/migrate/types.d.ts +110 -0
- package/dist/migrate/types.d.ts.map +1 -0
- package/dist/migrate/types.js +2 -0
- package/dist/migrate/types.js.map +1 -0
- package/dist/schema/project.d.ts +20 -9
- package/dist/schema/project.d.ts.map +1 -1
- package/dist/schema/project.js +127 -136
- package/dist/schema/project.js.map +1 -1
- package/dist/schema/project.test.js +22 -0
- package/dist/schema/project.test.js.map +1 -1
- package/package.json +2 -1
- package/src/api/resources.test.ts +121 -0
- package/src/api/resources.ts +292 -1
- package/src/cli/commands/migrate.test.ts +564 -0
- package/src/cli/commands/migrate.ts +240 -0
- package/src/cli/commands/pull.test.ts +173 -0
- package/src/cli/commands/pull.ts +177 -0
- package/src/cli/config.ts +26 -0
- package/src/cli/index.ts +112 -0
- package/src/generator/client.ts +2 -2
- package/src/index.ts +1 -1
- package/src/migrate/discovery.ts +151 -0
- package/src/migrate/emit-ts.ts +469 -0
- package/src/migrate/parse-connection.ts +128 -0
- package/src/migrate/parse-datasource.ts +453 -0
- package/src/migrate/parse-pipe.ts +518 -0
- package/src/migrate/parse.ts +20 -0
- package/src/migrate/parser-utils.ts +160 -0
- package/src/migrate/types.ts +125 -0
- package/src/schema/project.test.ts +28 -0
- package/src/schema/project.ts +173 -181
package/src/cli/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { runBuild } from "./commands/build.js";
|
|
|
20
20
|
import { runDeploy } from "./commands/deploy.js";
|
|
21
21
|
import { runPreview } from "./commands/preview.js";
|
|
22
22
|
import { runDev } from "./commands/dev.js";
|
|
23
|
+
import { runMigrate } from "./commands/migrate.js";
|
|
23
24
|
import { runLogin } from "./commands/login.js";
|
|
24
25
|
import {
|
|
25
26
|
runBranchList,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
} from "./commands/branch.js";
|
|
29
30
|
import { runClear } from "./commands/clear.js";
|
|
30
31
|
import { runInfo } from "./commands/info.js";
|
|
32
|
+
import { runPull } from "./commands/pull.js";
|
|
31
33
|
import {
|
|
32
34
|
runOpenDashboard,
|
|
33
35
|
type Environment,
|
|
@@ -179,6 +181,50 @@ function createCli(): Command {
|
|
|
179
181
|
}
|
|
180
182
|
});
|
|
181
183
|
|
|
184
|
+
// Pull command
|
|
185
|
+
program
|
|
186
|
+
.command("pull")
|
|
187
|
+
.description(
|
|
188
|
+
"Download datasources, pipes, and connections from Tinybird as datafiles"
|
|
189
|
+
)
|
|
190
|
+
.option(
|
|
191
|
+
"-o, --output-dir <path>",
|
|
192
|
+
"Directory where pulled files are written",
|
|
193
|
+
"."
|
|
194
|
+
)
|
|
195
|
+
.option("-f, --force", "Overwrite existing files")
|
|
196
|
+
.action(async (options) => {
|
|
197
|
+
output.highlight("Pulling resources from Tinybird...");
|
|
198
|
+
|
|
199
|
+
const result = await runPull({
|
|
200
|
+
outputDir: options.outputDir,
|
|
201
|
+
overwrite: options.force,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
if (!result.success) {
|
|
205
|
+
output.error(result.error ?? "Pull failed");
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const files = result.files ?? [];
|
|
210
|
+
const stats = result.stats ?? {
|
|
211
|
+
datasources: 0,
|
|
212
|
+
pipes: 0,
|
|
213
|
+
connections: 0,
|
|
214
|
+
total: files.length,
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
for (const file of files) {
|
|
218
|
+
const status = file.status === "created" ? "created" : "changed";
|
|
219
|
+
output.showResourceChange(file.relativePath, status);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
output.success(
|
|
223
|
+
`\nPulled ${stats.total} file(s): ${stats.datasources} datasource(s), ${stats.pipes} pipe(s), ${stats.connections} connection(s)`
|
|
224
|
+
);
|
|
225
|
+
output.success(`Completed in ${output.formatDuration(result.durationMs)}`);
|
|
226
|
+
});
|
|
227
|
+
|
|
182
228
|
// Open command
|
|
183
229
|
program
|
|
184
230
|
.command("open")
|
|
@@ -314,6 +360,72 @@ function createCli(): Command {
|
|
|
314
360
|
}
|
|
315
361
|
});
|
|
316
362
|
|
|
363
|
+
// Migrate command
|
|
364
|
+
program
|
|
365
|
+
.command("migrate")
|
|
366
|
+
.description(
|
|
367
|
+
"Migrate .datasource/.pipe/.connection files into TypeScript definitions"
|
|
368
|
+
)
|
|
369
|
+
.argument(
|
|
370
|
+
"<patterns...>",
|
|
371
|
+
"One or more file paths, directories, or glob patterns"
|
|
372
|
+
)
|
|
373
|
+
.option(
|
|
374
|
+
"-o, --out <path>",
|
|
375
|
+
"Output TypeScript path (default: ./tinybird.migration.ts)"
|
|
376
|
+
)
|
|
377
|
+
.option("--dry-run", "Preview migration without writing files")
|
|
378
|
+
.option("--force", "Overwrite output file if it already exists")
|
|
379
|
+
.option(
|
|
380
|
+
"--no-strict",
|
|
381
|
+
"Do not fail command when some resources cannot be migrated"
|
|
382
|
+
)
|
|
383
|
+
.action(async (patterns: string[], options) => {
|
|
384
|
+
const result = await runMigrate({
|
|
385
|
+
patterns,
|
|
386
|
+
out: options.out,
|
|
387
|
+
strict: options.strict,
|
|
388
|
+
dryRun: options.dryRun,
|
|
389
|
+
force: options.force,
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const migratedCounts = {
|
|
393
|
+
datasources: result.migrated.filter((resource) => resource.kind === "datasource")
|
|
394
|
+
.length,
|
|
395
|
+
pipes: result.migrated.filter((resource) => resource.kind === "pipe").length,
|
|
396
|
+
connections: result.migrated.filter(
|
|
397
|
+
(resource) => resource.kind === "connection"
|
|
398
|
+
).length,
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
console.log(
|
|
402
|
+
`Migrated: ${migratedCounts.datasources} datasource(s), ${migratedCounts.pipes} pipe(s), ${migratedCounts.connections} connection(s)`
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
if (result.migrated.length > 0) {
|
|
406
|
+
if (result.dryRun) {
|
|
407
|
+
console.log(`[Dry run] Output would be written to: ${result.outputPath}`);
|
|
408
|
+
} else {
|
|
409
|
+
console.log(`Output written to: ${result.outputPath}`);
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
console.log("No resources were migrated.");
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (result.errors.length > 0) {
|
|
416
|
+
console.log("\nErrors:");
|
|
417
|
+
for (const error of result.errors) {
|
|
418
|
+
console.log(
|
|
419
|
+
`- ${error.filePath} (${error.resourceKind}:${error.resourceName}): ${error.message}`
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (!result.success) {
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
317
429
|
// Deploy command
|
|
318
430
|
program
|
|
319
431
|
.command("deploy")
|
package/src/generator/client.ts
CHANGED
|
@@ -108,7 +108,7 @@ export function generateClientFile(options: GenerateClientOptions): GeneratedCli
|
|
|
108
108
|
sdkTypes.push("InferParams", "InferOutputRow");
|
|
109
109
|
}
|
|
110
110
|
importLines.push(
|
|
111
|
-
`import {
|
|
111
|
+
`import { Tinybird, type ${sdkTypes.join(", type ")} } from "@tinybirdco/sdk";`
|
|
112
112
|
);
|
|
113
113
|
// Node imports for deriving configDir from import.meta.url (monorepo support)
|
|
114
114
|
importLines.push(`import { fileURLToPath } from "url";`);
|
|
@@ -136,7 +136,7 @@ export function generateClientFile(options: GenerateClientOptions): GeneratedCli
|
|
|
136
136
|
// This ensures tinybird.json is found regardless of where the app runs from
|
|
137
137
|
clientLines.push("const __configDir = dirname(fileURLToPath(import.meta.url));");
|
|
138
138
|
clientLines.push("");
|
|
139
|
-
clientLines.push("export const tinybird =
|
|
139
|
+
clientLines.push("export const tinybird = new Tinybird({");
|
|
140
140
|
|
|
141
141
|
if (datasourceNames.length > 0) {
|
|
142
142
|
clientLines.push(` datasources: { ${datasourceNames.join(", ")} },`);
|
package/src/index.ts
CHANGED
|
@@ -168,7 +168,7 @@ export type {
|
|
|
168
168
|
} from "./schema/pipe.js";
|
|
169
169
|
|
|
170
170
|
// ============ Project ============
|
|
171
|
-
export { defineProject, isProjectDefinition, getDatasourceNames, getPipeNames, getDatasource, getPipe, createTinybirdClient } from "./schema/project.js";
|
|
171
|
+
export { defineProject, isProjectDefinition, getDatasourceNames, getPipeNames, getDatasource, getPipe, Tinybird, createTinybirdClient } from "./schema/project.js";
|
|
172
172
|
export type {
|
|
173
173
|
ProjectDefinition,
|
|
174
174
|
ProjectConfig,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { resolveIncludeFiles } from "../generator/include-paths.js";
|
|
4
|
+
import type { MigrationError, ResourceFile, ResourceKind } from "./types.js";
|
|
5
|
+
|
|
6
|
+
const SUPPORTED_EXTENSIONS = new Map<string, ResourceKind>([
|
|
7
|
+
[".datasource", "datasource"],
|
|
8
|
+
[".pipe", "pipe"],
|
|
9
|
+
[".connection", "connection"],
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
function normalizePath(filePath: string): string {
|
|
13
|
+
return filePath.replace(/\\/g, "/");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getKindFromPath(filePath: string): ResourceKind | null {
|
|
17
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
18
|
+
return SUPPORTED_EXTENSIONS.get(ext) ?? null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function collectDirectoryFiles(directory: string): string[] {
|
|
22
|
+
const entries = fs.readdirSync(directory, { withFileTypes: true });
|
|
23
|
+
const files: string[] = [];
|
|
24
|
+
|
|
25
|
+
for (const entry of entries) {
|
|
26
|
+
const fullPath = path.join(directory, entry.name);
|
|
27
|
+
|
|
28
|
+
if (entry.isDirectory()) {
|
|
29
|
+
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
files.push(...collectDirectoryFiles(fullPath));
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (entry.isFile()) {
|
|
37
|
+
files.push(fullPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return files;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface DiscoverResourcesResult {
|
|
45
|
+
resources: ResourceFile[];
|
|
46
|
+
errors: MigrationError[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function discoverResourceFiles(
|
|
50
|
+
patterns: string[],
|
|
51
|
+
cwd: string
|
|
52
|
+
): DiscoverResourcesResult {
|
|
53
|
+
const resources: ResourceFile[] = [];
|
|
54
|
+
const errors: MigrationError[] = [];
|
|
55
|
+
const seen = new Set<string>();
|
|
56
|
+
|
|
57
|
+
for (const pattern of patterns) {
|
|
58
|
+
const absolutePattern = path.isAbsolute(pattern)
|
|
59
|
+
? pattern
|
|
60
|
+
: path.resolve(cwd, pattern);
|
|
61
|
+
|
|
62
|
+
if (fs.existsSync(absolutePattern)) {
|
|
63
|
+
const stat = fs.statSync(absolutePattern);
|
|
64
|
+
|
|
65
|
+
if (stat.isDirectory()) {
|
|
66
|
+
const directoryFiles = collectDirectoryFiles(absolutePattern);
|
|
67
|
+
for (const absoluteFilePath of directoryFiles) {
|
|
68
|
+
const kind = getKindFromPath(absoluteFilePath);
|
|
69
|
+
if (!kind) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const key = normalizePath(absoluteFilePath);
|
|
74
|
+
if (seen.has(key)) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
seen.add(key);
|
|
78
|
+
|
|
79
|
+
const relativePath = normalizePath(path.relative(cwd, absoluteFilePath));
|
|
80
|
+
const name = path.basename(absoluteFilePath, path.extname(absoluteFilePath));
|
|
81
|
+
resources.push({
|
|
82
|
+
kind,
|
|
83
|
+
filePath: relativePath,
|
|
84
|
+
absolutePath: absoluteFilePath,
|
|
85
|
+
name,
|
|
86
|
+
content: fs.readFileSync(absoluteFilePath, "utf-8"),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const kind = getKindFromPath(absolutePattern);
|
|
93
|
+
if (!kind) {
|
|
94
|
+
errors.push({
|
|
95
|
+
filePath: pattern,
|
|
96
|
+
resourceName: path.basename(absolutePattern),
|
|
97
|
+
resourceKind: "datasource",
|
|
98
|
+
message: `Unsupported file extension: ${path.extname(absolutePattern) || "(none)"}. Use .datasource, .pipe, or .connection.`,
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const key = normalizePath(absolutePattern);
|
|
104
|
+
if (seen.has(key)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
seen.add(key);
|
|
108
|
+
resources.push({
|
|
109
|
+
kind,
|
|
110
|
+
filePath: normalizePath(path.relative(cwd, absolutePattern)),
|
|
111
|
+
absolutePath: absolutePattern,
|
|
112
|
+
name: path.basename(absolutePattern, path.extname(absolutePattern)),
|
|
113
|
+
content: fs.readFileSync(absolutePattern, "utf-8"),
|
|
114
|
+
});
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const matched = resolveIncludeFiles([pattern], cwd);
|
|
120
|
+
for (const entry of matched) {
|
|
121
|
+
const kind = getKindFromPath(entry.absolutePath);
|
|
122
|
+
if (!kind) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const key = normalizePath(entry.absolutePath);
|
|
126
|
+
if (seen.has(key)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
seen.add(key);
|
|
130
|
+
resources.push({
|
|
131
|
+
kind,
|
|
132
|
+
filePath: normalizePath(entry.sourcePath),
|
|
133
|
+
absolutePath: entry.absolutePath,
|
|
134
|
+
name: path.basename(entry.absolutePath, path.extname(entry.absolutePath)),
|
|
135
|
+
content: fs.readFileSync(entry.absolutePath, "utf-8"),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
errors.push({
|
|
140
|
+
filePath: pattern,
|
|
141
|
+
resourceName: path.basename(pattern),
|
|
142
|
+
resourceKind: "datasource",
|
|
143
|
+
message: (error as Error).message,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
resources.sort((a, b) => a.filePath.localeCompare(b.filePath));
|
|
149
|
+
return { resources, errors };
|
|
150
|
+
}
|
|
151
|
+
|