@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
package/src/cli/config.test.ts
CHANGED
|
@@ -4,10 +4,8 @@ import * as path from "path";
|
|
|
4
4
|
import * as os from "os";
|
|
5
5
|
import {
|
|
6
6
|
hasSrcFolder,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
getTinybirdSchemaPath,
|
|
10
|
-
getRelativeSchemaPath,
|
|
7
|
+
getTinybirdDir,
|
|
8
|
+
getRelativeTinybirdDir,
|
|
11
9
|
findConfigFile,
|
|
12
10
|
loadConfig,
|
|
13
11
|
getConfigPath,
|
|
@@ -50,55 +48,27 @@ describe("Config", () => {
|
|
|
50
48
|
});
|
|
51
49
|
});
|
|
52
50
|
|
|
53
|
-
describe("
|
|
54
|
-
it("returns src/
|
|
51
|
+
describe("getTinybirdDir", () => {
|
|
52
|
+
it("returns src/lib when project has src folder", () => {
|
|
55
53
|
fs.mkdirSync(path.join(tempDir, "src"));
|
|
56
54
|
|
|
57
|
-
expect(
|
|
55
|
+
expect(getTinybirdDir(tempDir)).toBe(path.join(tempDir, "src", "lib"));
|
|
58
56
|
});
|
|
59
57
|
|
|
60
|
-
it("returns
|
|
61
|
-
expect(
|
|
58
|
+
it("returns lib when project does not have src folder", () => {
|
|
59
|
+
expect(getTinybirdDir(tempDir)).toBe(path.join(tempDir, "lib"));
|
|
62
60
|
});
|
|
63
61
|
});
|
|
64
62
|
|
|
65
|
-
describe("
|
|
66
|
-
it("returns src/tinybird when project has src folder", () => {
|
|
63
|
+
describe("getRelativeTinybirdDir", () => {
|
|
64
|
+
it("returns src/lib/tinybird.ts when project has src folder", () => {
|
|
67
65
|
fs.mkdirSync(path.join(tempDir, "src"));
|
|
68
66
|
|
|
69
|
-
expect(
|
|
67
|
+
expect(getRelativeTinybirdDir(tempDir)).toBe("src/lib/tinybird.ts");
|
|
70
68
|
});
|
|
71
69
|
|
|
72
|
-
it("returns tinybird when project does not have src folder", () => {
|
|
73
|
-
expect(
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe("getTinybirdSchemaPath", () => {
|
|
78
|
-
it("returns src/tinybird/datasources.ts when project has src folder", () => {
|
|
79
|
-
fs.mkdirSync(path.join(tempDir, "src"));
|
|
80
|
-
|
|
81
|
-
expect(getTinybirdSchemaPath(tempDir)).toBe(
|
|
82
|
-
path.join(tempDir, "src", "tinybird", "datasources.ts")
|
|
83
|
-
);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("returns tinybird/datasources.ts when project does not have src folder", () => {
|
|
87
|
-
expect(getTinybirdSchemaPath(tempDir)).toBe(
|
|
88
|
-
path.join(tempDir, "tinybird", "datasources.ts")
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe("getRelativeSchemaPath", () => {
|
|
94
|
-
it("returns src/tinybird/datasources.ts when project has src folder", () => {
|
|
95
|
-
fs.mkdirSync(path.join(tempDir, "src"));
|
|
96
|
-
|
|
97
|
-
expect(getRelativeSchemaPath(tempDir)).toBe("src/tinybird/datasources.ts");
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("returns tinybird/datasources.ts when project does not have src folder", () => {
|
|
101
|
-
expect(getRelativeSchemaPath(tempDir)).toBe("tinybird/datasources.ts");
|
|
70
|
+
it("returns lib/tinybird.ts when project does not have src folder", () => {
|
|
71
|
+
expect(getRelativeTinybirdDir(tempDir)).toBe("lib/tinybird.ts");
|
|
102
72
|
});
|
|
103
73
|
});
|
|
104
74
|
|
package/src/cli/config.ts
CHANGED
|
@@ -69,9 +69,9 @@ export const LOCAL_BASE_URL = "http://localhost:7181";
|
|
|
69
69
|
const CONFIG_FILE = "tinybird.json";
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* Tinybird folder
|
|
72
|
+
* Tinybird file path within lib folder
|
|
73
73
|
*/
|
|
74
|
-
const
|
|
74
|
+
const TINYBIRD_FILE = "lib/tinybird.ts";
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* Detect if project has a src folder
|
|
@@ -82,18 +82,20 @@ export function hasSrcFolder(cwd: string): boolean {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
* Get the tinybird
|
|
86
|
-
* Returns 'src/tinybird' if project has src folder, otherwise 'tinybird'
|
|
85
|
+
* Get the tinybird file path based on project structure
|
|
86
|
+
* Returns 'src/lib/tinybird.ts' if project has src folder, otherwise 'lib/tinybird.ts'
|
|
87
87
|
*/
|
|
88
88
|
export function getTinybirdDir(cwd: string): string {
|
|
89
|
-
return hasSrcFolder(cwd)
|
|
89
|
+
return hasSrcFolder(cwd)
|
|
90
|
+
? path.join(cwd, "src", "lib")
|
|
91
|
+
: path.join(cwd, "lib");
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
/**
|
|
93
|
-
* Get the relative tinybird
|
|
95
|
+
* Get the relative tinybird file path based on project structure
|
|
94
96
|
*/
|
|
95
97
|
export function getRelativeTinybirdDir(cwd: string): string {
|
|
96
|
-
return hasSrcFolder(cwd) ? `src/${
|
|
98
|
+
return hasSrcFolder(cwd) ? `src/${TINYBIRD_FILE}` : TINYBIRD_FILE;
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
/**
|
|
@@ -117,22 +119,6 @@ export function getClientPath(cwd: string): string {
|
|
|
117
119
|
return path.join(getTinybirdDir(cwd), "client.ts");
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
// Legacy exports for backwards compatibility
|
|
121
|
-
export function getLibDir(cwd: string): string {
|
|
122
|
-
return getTinybirdDir(cwd);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function getRelativeLibDir(cwd: string): string {
|
|
126
|
-
return getRelativeTinybirdDir(cwd);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function getTinybirdSchemaPath(cwd: string): string {
|
|
130
|
-
return getDatasourcesPath(cwd);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function getRelativeSchemaPath(cwd: string): string {
|
|
134
|
-
return `${getRelativeTinybirdDir(cwd)}/datasources.ts`;
|
|
135
|
-
}
|
|
136
122
|
|
|
137
123
|
/**
|
|
138
124
|
* Interpolate environment variables in a string
|
package/src/cli/git.ts
CHANGED
|
@@ -97,6 +97,21 @@ export function isGitRepo(): boolean {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Get the root directory of the git repository
|
|
102
|
+
* Returns null if not in a git repo
|
|
103
|
+
*/
|
|
104
|
+
export function getGitRoot(): string | null {
|
|
105
|
+
try {
|
|
106
|
+
return execSync("git rev-parse --show-toplevel", {
|
|
107
|
+
encoding: "utf-8",
|
|
108
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
109
|
+
}).trim();
|
|
110
|
+
} catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
100
115
|
/**
|
|
101
116
|
* Sanitize a git branch name for use as a Tinybird branch name
|
|
102
117
|
* Tinybird only accepts alphanumeric characters and underscores
|
package/src/cli/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ config({ path: ".env" });
|
|
|
12
12
|
|
|
13
13
|
import { readFileSync } from "node:fs";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
15
|
-
import { dirname, resolve } from "node:path";
|
|
15
|
+
import { dirname, join, resolve } from "node:path";
|
|
16
16
|
import { Command } from "commander";
|
|
17
17
|
import { runInit } from "./commands/init.js";
|
|
18
18
|
import { runBuild } from "./commands/build.js";
|
|
@@ -24,7 +24,11 @@ import {
|
|
|
24
24
|
runBranchStatus,
|
|
25
25
|
runBranchDelete,
|
|
26
26
|
} from "./commands/branch.js";
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
detectPackageManagerInstallCmd,
|
|
29
|
+
detectPackageManagerRunCmd,
|
|
30
|
+
hasTinybirdSdkDependency,
|
|
31
|
+
} from "./utils/package-manager.js";
|
|
28
32
|
import type { DevMode } from "./config.js";
|
|
29
33
|
|
|
30
34
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -80,23 +84,14 @@ function createCli(): Command {
|
|
|
80
84
|
process.exit(1);
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
if (result.created.length > 0) {
|
|
84
|
-
console.log("Created:");
|
|
85
|
-
result.created.forEach((file) => {
|
|
86
|
-
console.log(` - ${file}`);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (result.skipped.length > 0) {
|
|
91
|
-
console.log("\nSkipped (already exists):");
|
|
92
|
-
result.skipped.forEach((file) => {
|
|
93
|
-
console.log(` - ${file}`);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
87
|
// Detect package manager for run command
|
|
98
|
-
const runCmd = detectPackageManagerRunCmd();
|
|
99
88
|
const clientPath = result.clientPath ?? "tinybird";
|
|
89
|
+
const sdkCheckDir = result.clientPath
|
|
90
|
+
? dirname(join(process.cwd(), clientPath))
|
|
91
|
+
: process.cwd();
|
|
92
|
+
const runCmd = detectPackageManagerRunCmd(sdkCheckDir);
|
|
93
|
+
const installCmd = detectPackageManagerInstallCmd(sdkCheckDir);
|
|
94
|
+
const needsInstallStep = !hasTinybirdSdkDependency(sdkCheckDir);
|
|
100
95
|
|
|
101
96
|
if (result.loggedIn) {
|
|
102
97
|
console.log(`\nLogged in successfully!`);
|
|
@@ -112,19 +107,43 @@ function createCli(): Command {
|
|
|
112
107
|
`\nAdded ${result.existingDatafiles.length} existing datafile(s) to tinybird.json.`
|
|
113
108
|
);
|
|
114
109
|
}
|
|
115
|
-
console.log("\
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
console.log("\nNext steps:");
|
|
111
|
+
const steps = [
|
|
112
|
+
needsInstallStep
|
|
113
|
+
? `Install dependencies with '${installCmd}'`
|
|
114
|
+
: undefined,
|
|
115
|
+
`Edit your schema in ${clientPath}`,
|
|
116
|
+
`Run '${runCmd} tinybird:dev' to start development`,
|
|
117
|
+
].filter(Boolean);
|
|
118
|
+
steps.forEach((step, index) => {
|
|
119
|
+
console.log(` ${index + 1}. ${step}`);
|
|
120
|
+
});
|
|
118
121
|
} else if (result.loggedIn === false) {
|
|
119
122
|
console.log("\nLogin was skipped or failed.");
|
|
120
|
-
console.log("\
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
console.log("\nNext steps:");
|
|
124
|
+
const steps = [
|
|
125
|
+
"Run 'npx tinybird login' to authenticate",
|
|
126
|
+
needsInstallStep
|
|
127
|
+
? `Install dependencies with '${installCmd}'`
|
|
128
|
+
: undefined,
|
|
129
|
+
`Edit your schema in ${clientPath}`,
|
|
130
|
+
`Run '${runCmd} tinybird:dev' to start development`,
|
|
131
|
+
].filter(Boolean);
|
|
132
|
+
steps.forEach((step, index) => {
|
|
133
|
+
console.log(` ${index + 1}. ${step}`);
|
|
134
|
+
});
|
|
124
135
|
} else {
|
|
125
|
-
console.log("\
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
console.log("\nNext steps:");
|
|
137
|
+
const steps = [
|
|
138
|
+
needsInstallStep
|
|
139
|
+
? `Install dependencies with '${installCmd}'`
|
|
140
|
+
: undefined,
|
|
141
|
+
`Edit your schema in ${clientPath}`,
|
|
142
|
+
`Run '${runCmd} tinybird:dev' to start development`,
|
|
143
|
+
].filter(Boolean);
|
|
144
|
+
steps.forEach((step, index) => {
|
|
145
|
+
console.log(` ${index + 1}. ${step}`);
|
|
146
|
+
});
|
|
128
147
|
}
|
|
129
148
|
});
|
|
130
149
|
|
|
@@ -2,55 +2,62 @@ import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import * as os from "os";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
import {
|
|
6
|
+
detectPackageManager,
|
|
7
|
+
detectPackageManagerInstallCmd,
|
|
8
|
+
detectPackageManagerRunCmd,
|
|
9
|
+
getPackageManagerInstallCmd,
|
|
10
|
+
getPackageManagerRunCmd,
|
|
11
|
+
hasTinybirdSdkDependency,
|
|
12
|
+
} from "./package-manager.js";
|
|
13
|
+
|
|
14
|
+
let tempDir: string;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pkg-manager-test-"));
|
|
18
|
+
});
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
try {
|
|
22
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
23
|
+
} catch {
|
|
24
|
+
// Ignore cleanup errors
|
|
25
|
+
}
|
|
26
|
+
});
|
|
21
27
|
|
|
28
|
+
describe("detectPackageManager", () => {
|
|
22
29
|
describe("lockfile detection", () => {
|
|
23
30
|
it("detects pnpm from pnpm-lock.yaml", () => {
|
|
24
31
|
fs.writeFileSync(path.join(tempDir, "pnpm-lock.yaml"), "");
|
|
25
|
-
expect(
|
|
32
|
+
expect(detectPackageManager(tempDir)).toBe("pnpm");
|
|
26
33
|
});
|
|
27
34
|
|
|
28
35
|
it("detects yarn from yarn.lock", () => {
|
|
29
36
|
fs.writeFileSync(path.join(tempDir, "yarn.lock"), "");
|
|
30
|
-
expect(
|
|
37
|
+
expect(detectPackageManager(tempDir)).toBe("yarn");
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
it("detects bun from bun.lockb", () => {
|
|
34
41
|
fs.writeFileSync(path.join(tempDir, "bun.lockb"), "");
|
|
35
|
-
expect(
|
|
42
|
+
expect(detectPackageManager(tempDir)).toBe("bun");
|
|
36
43
|
});
|
|
37
44
|
|
|
38
45
|
it("detects npm from package-lock.json", () => {
|
|
39
46
|
fs.writeFileSync(path.join(tempDir, "package-lock.json"), "{}");
|
|
40
|
-
expect(
|
|
47
|
+
expect(detectPackageManager(tempDir)).toBe("npm");
|
|
41
48
|
});
|
|
42
49
|
|
|
43
50
|
it("prioritizes pnpm lockfile over others", () => {
|
|
44
51
|
fs.writeFileSync(path.join(tempDir, "pnpm-lock.yaml"), "");
|
|
45
52
|
fs.writeFileSync(path.join(tempDir, "yarn.lock"), "");
|
|
46
53
|
fs.writeFileSync(path.join(tempDir, "package-lock.json"), "{}");
|
|
47
|
-
expect(
|
|
54
|
+
expect(detectPackageManager(tempDir)).toBe("pnpm");
|
|
48
55
|
});
|
|
49
56
|
|
|
50
57
|
it("prioritizes yarn lockfile over npm", () => {
|
|
51
58
|
fs.writeFileSync(path.join(tempDir, "yarn.lock"), "");
|
|
52
59
|
fs.writeFileSync(path.join(tempDir, "package-lock.json"), "{}");
|
|
53
|
-
expect(
|
|
60
|
+
expect(detectPackageManager(tempDir)).toBe("yarn");
|
|
54
61
|
});
|
|
55
62
|
});
|
|
56
63
|
|
|
@@ -60,7 +67,7 @@ describe("detectPackageManagerRunCmd", () => {
|
|
|
60
67
|
path.join(tempDir, "package.json"),
|
|
61
68
|
JSON.stringify({ packageManager: "pnpm@9.0.0" })
|
|
62
69
|
);
|
|
63
|
-
expect(
|
|
70
|
+
expect(detectPackageManager(tempDir)).toBe("pnpm");
|
|
64
71
|
});
|
|
65
72
|
|
|
66
73
|
it("detects yarn from packageManager field", () => {
|
|
@@ -68,7 +75,7 @@ describe("detectPackageManagerRunCmd", () => {
|
|
|
68
75
|
path.join(tempDir, "package.json"),
|
|
69
76
|
JSON.stringify({ packageManager: "yarn@4.0.0" })
|
|
70
77
|
);
|
|
71
|
-
expect(
|
|
78
|
+
expect(detectPackageManager(tempDir)).toBe("yarn");
|
|
72
79
|
});
|
|
73
80
|
|
|
74
81
|
it("detects bun from packageManager field", () => {
|
|
@@ -76,7 +83,15 @@ describe("detectPackageManagerRunCmd", () => {
|
|
|
76
83
|
path.join(tempDir, "package.json"),
|
|
77
84
|
JSON.stringify({ packageManager: "bun@1.0.0" })
|
|
78
85
|
);
|
|
79
|
-
expect(
|
|
86
|
+
expect(detectPackageManager(tempDir)).toBe("bun");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("detects npm from packageManager field", () => {
|
|
90
|
+
fs.writeFileSync(
|
|
91
|
+
path.join(tempDir, "package.json"),
|
|
92
|
+
JSON.stringify({ packageManager: "npm@10.0.0" })
|
|
93
|
+
);
|
|
94
|
+
expect(detectPackageManager(tempDir)).toBe("npm");
|
|
80
95
|
});
|
|
81
96
|
|
|
82
97
|
it("prioritizes lockfile over packageManager field", () => {
|
|
@@ -85,34 +100,151 @@ describe("detectPackageManagerRunCmd", () => {
|
|
|
85
100
|
path.join(tempDir, "package.json"),
|
|
86
101
|
JSON.stringify({ packageManager: "pnpm@9.0.0" })
|
|
87
102
|
);
|
|
88
|
-
expect(
|
|
103
|
+
expect(detectPackageManager(tempDir)).toBe("yarn");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe("monorepo detection", () => {
|
|
108
|
+
it("detects pnpm from workspace root when inside a package", () => {
|
|
109
|
+
const repoRoot = path.join(tempDir, "repo");
|
|
110
|
+
const packageDir = path.join(repoRoot, "packages", "app");
|
|
111
|
+
fs.mkdirSync(packageDir, { recursive: true });
|
|
112
|
+
fs.writeFileSync(path.join(repoRoot, "pnpm-workspace.yaml"), "packages:\n - packages/*\n");
|
|
113
|
+
fs.writeFileSync(path.join(repoRoot, "pnpm-lock.yaml"), "");
|
|
114
|
+
expect(detectPackageManager(packageDir)).toBe("pnpm");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("detects pnpm from workspace config even without a lockfile", () => {
|
|
118
|
+
const repoRoot = path.join(tempDir, "repo");
|
|
119
|
+
const packageDir = path.join(repoRoot, "packages", "app");
|
|
120
|
+
fs.mkdirSync(packageDir, { recursive: true });
|
|
121
|
+
fs.writeFileSync(path.join(repoRoot, "pnpm-workspace.yaml"), "packages:\n - packages/*\n");
|
|
122
|
+
expect(detectPackageManager(packageDir)).toBe("pnpm");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("prefers the nearest lockfile in nested packages", () => {
|
|
126
|
+
const repoRoot = path.join(tempDir, "repo");
|
|
127
|
+
const packageDir = path.join(repoRoot, "packages", "app");
|
|
128
|
+
fs.mkdirSync(packageDir, { recursive: true });
|
|
129
|
+
fs.writeFileSync(path.join(repoRoot, "pnpm-lock.yaml"), "");
|
|
130
|
+
fs.writeFileSync(path.join(packageDir, "yarn.lock"), "");
|
|
131
|
+
expect(detectPackageManager(packageDir)).toBe("yarn");
|
|
89
132
|
});
|
|
90
133
|
});
|
|
91
134
|
|
|
92
135
|
describe("default behavior", () => {
|
|
93
|
-
it("defaults to npm
|
|
94
|
-
expect(
|
|
136
|
+
it("defaults to npm when no indicators found", () => {
|
|
137
|
+
expect(detectPackageManager(tempDir)).toBe("npm");
|
|
95
138
|
});
|
|
96
139
|
|
|
97
|
-
it("defaults to npm
|
|
140
|
+
it("defaults to npm when package.json has no packageManager field", () => {
|
|
98
141
|
fs.writeFileSync(
|
|
99
142
|
path.join(tempDir, "package.json"),
|
|
100
143
|
JSON.stringify({ name: "test-project" })
|
|
101
144
|
);
|
|
102
|
-
expect(
|
|
145
|
+
expect(detectPackageManager(tempDir)).toBe("npm");
|
|
103
146
|
});
|
|
104
147
|
|
|
105
|
-
it("defaults to npm
|
|
148
|
+
it("defaults to npm when package.json is invalid JSON", () => {
|
|
106
149
|
fs.writeFileSync(path.join(tempDir, "package.json"), "not json");
|
|
107
|
-
expect(
|
|
150
|
+
expect(detectPackageManager(tempDir)).toBe("npm");
|
|
108
151
|
});
|
|
109
152
|
|
|
110
|
-
it("defaults to npm
|
|
153
|
+
it("defaults to npm when packageManager is not a string", () => {
|
|
111
154
|
fs.writeFileSync(
|
|
112
155
|
path.join(tempDir, "package.json"),
|
|
113
156
|
JSON.stringify({ packageManager: 123 })
|
|
114
157
|
);
|
|
115
|
-
expect(
|
|
158
|
+
expect(detectPackageManager(tempDir)).toBe("npm");
|
|
116
159
|
});
|
|
117
160
|
});
|
|
118
161
|
});
|
|
162
|
+
|
|
163
|
+
describe("getPackageManagerRunCmd", () => {
|
|
164
|
+
it("maps npm to npm run", () => {
|
|
165
|
+
expect(getPackageManagerRunCmd("npm")).toBe("npm run");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("maps pnpm to pnpm run", () => {
|
|
169
|
+
expect(getPackageManagerRunCmd("pnpm")).toBe("pnpm run");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("maps yarn to yarn", () => {
|
|
173
|
+
expect(getPackageManagerRunCmd("yarn")).toBe("yarn");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("maps bun to bun run", () => {
|
|
177
|
+
expect(getPackageManagerRunCmd("bun")).toBe("bun run");
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe("getPackageManagerInstallCmd", () => {
|
|
182
|
+
it("maps npm to npm install", () => {
|
|
183
|
+
expect(getPackageManagerInstallCmd("npm")).toBe("npm install");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("maps pnpm to pnpm install", () => {
|
|
187
|
+
expect(getPackageManagerInstallCmd("pnpm")).toBe("pnpm install");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it("maps yarn to yarn install", () => {
|
|
191
|
+
expect(getPackageManagerInstallCmd("yarn")).toBe("yarn install");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("maps bun to bun install", () => {
|
|
195
|
+
expect(getPackageManagerInstallCmd("bun")).toBe("bun install");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe("detectPackageManagerInstallCmd", () => {
|
|
200
|
+
it("detects install command based on lockfile", () => {
|
|
201
|
+
fs.writeFileSync(path.join(tempDir, "yarn.lock"), "");
|
|
202
|
+
expect(detectPackageManagerInstallCmd(tempDir)).toBe("yarn install");
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe("hasTinybirdSdkDependency", () => {
|
|
207
|
+
it("returns true when sdk is in dependencies", () => {
|
|
208
|
+
fs.writeFileSync(
|
|
209
|
+
path.join(tempDir, "package.json"),
|
|
210
|
+
JSON.stringify({ dependencies: { "@tinybirdco/sdk": "^1.0.0" } })
|
|
211
|
+
);
|
|
212
|
+
expect(hasTinybirdSdkDependency(tempDir)).toBe(true);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("returns true when sdk is in devDependencies", () => {
|
|
216
|
+
fs.writeFileSync(
|
|
217
|
+
path.join(tempDir, "package.json"),
|
|
218
|
+
JSON.stringify({ devDependencies: { "@tinybirdco/sdk": "^1.0.0" } })
|
|
219
|
+
);
|
|
220
|
+
expect(hasTinybirdSdkDependency(tempDir)).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("returns false when package.json is missing or invalid", () => {
|
|
224
|
+
expect(hasTinybirdSdkDependency(tempDir)).toBe(false);
|
|
225
|
+
fs.writeFileSync(path.join(tempDir, "package.json"), "not json");
|
|
226
|
+
expect(hasTinybirdSdkDependency(tempDir)).toBe(false);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("checks the nearest package.json", () => {
|
|
230
|
+
const repoRoot = path.join(tempDir, "repo");
|
|
231
|
+
const packageDir = path.join(repoRoot, "packages", "app");
|
|
232
|
+
fs.mkdirSync(packageDir, { recursive: true });
|
|
233
|
+
fs.writeFileSync(
|
|
234
|
+
path.join(repoRoot, "package.json"),
|
|
235
|
+
JSON.stringify({ dependencies: { "@tinybirdco/sdk": "^1.0.0" } })
|
|
236
|
+
);
|
|
237
|
+
fs.writeFileSync(
|
|
238
|
+
path.join(packageDir, "package.json"),
|
|
239
|
+
JSON.stringify({ dependencies: { other: "^1.0.0" } })
|
|
240
|
+
);
|
|
241
|
+
expect(hasTinybirdSdkDependency(packageDir)).toBe(false);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe("detectPackageManagerRunCmd", () => {
|
|
246
|
+
it("uses the package manager detection and mapping", () => {
|
|
247
|
+
fs.writeFileSync(path.join(tempDir, "pnpm-lock.yaml"), "");
|
|
248
|
+
expect(detectPackageManagerRunCmd(tempDir)).toBe("pnpm run");
|
|
249
|
+
});
|
|
250
|
+
});
|