Skip to content

Commit 61e4ece

Browse files
update base project locator
1 parent c61acb2 commit 61e4ece

File tree

8 files changed

+214
-20
lines changed

8 files changed

+214
-20
lines changed

cli/_utils/path/index.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11
import fs from "fs";
22
import path from "path";
3-
3+
import glob from "glob";
44
/**
55
* finds file with name in cwd
66
*
77
* e.g. package.json -> <cwd>/package.json
8+
* e.g. pubspec.y{,a}ml -> <cwd>/pubspec.yaml
89
*
910
* @param name
1011
* @param cwd
1112
* @returns
1213
*/
13-
export function find_in_cwd(name, cwd = process.cwd()) {
14-
const file = path.join(cwd, name);
15-
if (fs.existsSync(file)) {
16-
return file;
14+
export function find_in_cwd(name, cwd = process.cwd(), useglob = false) {
15+
if (useglob) {
16+
const file = glob.sync(name, { cwd }).pop() || null;
17+
if (file) {
18+
return path.resolve(cwd, file);
19+
}
20+
} else {
21+
const file = path.join(cwd, name);
22+
23+
if (fs.existsSync(file)) {
24+
return file;
25+
}
26+
return null;
1727
}
18-
return null;
1928
}
2029

2130
/**
@@ -26,17 +35,29 @@ export function find_in_cwd(name, cwd = process.cwd()) {
2635
* ../../../package.json
2736
* ...
2837
*/
29-
export function find_in_parent(name, cwd = process.cwd(), recursively = true) {
38+
export function find_in_parent(
39+
name,
40+
cwd = process.cwd(),
41+
recursively = true,
42+
useglob = false
43+
) {
3044
const parent_dir = path.dirname(cwd);
3145
if (parent_dir === cwd) {
3246
return null;
3347
}
34-
const file = path.join(parent_dir, name);
35-
if (fs.existsSync(file)) {
36-
return file;
48+
if (useglob) {
49+
const file = glob.sync(name, { cwd: parent_dir }).pop() || null;
50+
if (file) {
51+
return path.join(parent_dir, file);
52+
}
53+
} else {
54+
const file = path.join(parent_dir, name);
55+
if (fs.existsSync(file)) {
56+
return file;
57+
}
3758
}
3859
if (recursively) {
39-
return find_in_parent(name, parent_dir, recursively);
60+
return find_in_parent(name, parent_dir, recursively, useglob);
4061
}
4162
return null;
4263
}

cli/npm/index.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const _PACKAGE_JSON = "package.json";
77
/**
88
* finds a npm pacakge root with package.json search
99
*/
10-
export function locatePackage(cwd = process.cwd()): {
10+
export function locateNodePackage(cwd = process.cwd()): {
1111
base_dir: string;
1212
package_json: string;
1313
manifest: IPackageManifest;
@@ -39,3 +39,62 @@ export function locatePackage(cwd = process.cwd()): {
3939
export function read(path): IPackageManifest {
4040
return require(path);
4141
}
42+
43+
export function analyzeFramework(manifest: IPackageManifest): {
44+
framework: "react" | "react-native" | "solid-js" | "svelte" | "vue";
45+
packages?: string[];
46+
} {
47+
const deps = new Set(Object.keys(manifest.dependencies || {}));
48+
const devdeps = new Set(Object.keys(manifest.devDependencies || {}));
49+
const alldeps = new Set([...deps, ...devdeps]);
50+
51+
// framework
52+
const isreact = alldeps.has("react");
53+
const isreactnative = alldeps.has("react-native");
54+
const isvue3 = alldeps.has("vue");
55+
const issvelte = alldeps.has("svelte");
56+
const issolidjs = alldeps.has("solid-js");
57+
58+
// managed packages
59+
const namedpackages = [
60+
"styled-components",
61+
"@emotion/styled",
62+
"@emotion/native",
63+
];
64+
65+
const packages = namedpackages
66+
.map((k) => {
67+
if (alldeps.has(k)) {
68+
return k;
69+
}
70+
})
71+
.filter(Boolean);
72+
73+
if (isreact) {
74+
if (isreactnative) {
75+
return { framework: "react-native", packages: packages };
76+
}
77+
return { framework: "react", packages: packages };
78+
}
79+
80+
if (isvue3) {
81+
return {
82+
framework: "vue",
83+
packages: packages,
84+
};
85+
}
86+
87+
if (issvelte) {
88+
return {
89+
framework: "svelte",
90+
packages: packages,
91+
};
92+
}
93+
94+
if (issolidjs) {
95+
return {
96+
framework: "solid-js",
97+
packages: packages,
98+
};
99+
}
100+
}

cli/project/__test__/find-project.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
import { locateProject, read } from "../index";
1+
import { locateGridaProject, read } from "../index";
22
import path from "path";
33

44
test("find grida project cwd", () => {
5-
const _ = locateProject(__dirname);
5+
const _ = locateGridaProject(__dirname);
66
expect(_?.config_file).toBe(path.join(__dirname, "grida.config.js"));
77
});
88

99
test("find grida project from subdir", () => {
10-
const _ = locateProject(path.join(__dirname, "sub-dir-for-testing"));
10+
const _ = locateGridaProject(path.join(__dirname, "sub-dir-for-testing"));
1111
expect(_?.config_file).toBe(path.join(__dirname, "grida.config.js"));
1212
});
1313

1414
test("find grida project from subdir (deep)", () => {
15-
const _ = locateProject(
15+
const _ = locateGridaProject(
1616
path.join(__dirname, "sub-dir-for-testing", "another-nested-dir")
1717
);
1818
expect(_?.config_file).toBe(path.join(__dirname, "grida.config.js"));
1919
});
2020

2121
test("read config", () => {
22-
const _ = locateProject(
22+
const _ = locateGridaProject(
2323
path.join(__dirname, "sub-dir-for-testing", "another-nested-dir")
2424
);
2525
expect(read(_?.config_file).name).toBe("__test__");

cli/project/index.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import { BuilderConfig } from "@grida/builder-config";
1+
import { BuilderConfig, FrameworkConfig } from "@grida/builder-config";
22
import path from "path";
3+
import {
4+
analyzeFramework as analyzeJsFramework,
5+
locateNodePackage,
6+
} from "../npm";
7+
import { analyzeFramework as analyzePubFramework, locatePubspec } from "../pub";
38
import { find_in_cwd, find_in_parent } from "../_utils/path";
49

510
const _GRIDA_CONFIG_JS = "grida.config.js";
@@ -24,7 +29,7 @@ export function read(path): BuilderConfig {
2429
* @param cwd
2530
* @returns
2631
*/
27-
export function locateProject(
32+
export function locateGridaProject(
2833
cwd = process.cwd()
2934
): GridaProjectSearchResult | null {
3035
const grida_config_js = find_in_cwd(_GRIDA_CONFIG_JS, cwd);
@@ -49,3 +54,50 @@ export function locateProject(
4954
}
5055
return null;
5156
}
57+
58+
export function locateBaseProject(cwd = process.cwd()): {
59+
base_dir: string;
60+
name: string;
61+
config_file: string;
62+
framework: FrameworkConfig["framework"];
63+
packages?: string[];
64+
} {
65+
const pubspec = locatePubspec(cwd);
66+
const npm = locateNodePackage(cwd);
67+
68+
if (npm && pubspec) {
69+
throw new Error(
70+
`Invalid project root configuration. both pubspec.yaml and package.json found from ${cwd}`
71+
);
72+
}
73+
74+
if (npm) {
75+
const res = analyzeJsFramework(npm.manifest);
76+
if (res) {
77+
if (res.framework === "vue") {
78+
throw new Error("Vue is not supported yet");
79+
}
80+
if (res.framework === "svelte") {
81+
throw new Error("Svelte is not supported yet");
82+
}
83+
return {
84+
base_dir: npm.base_dir,
85+
name: npm.manifest.name,
86+
config_file: npm.package_json,
87+
...(res as any),
88+
};
89+
}
90+
}
91+
92+
if (pubspec) {
93+
const res = analyzePubFramework(pubspec.manifest);
94+
if (res) {
95+
return {
96+
base_dir: pubspec.base_dir,
97+
name: pubspec.manifest.name,
98+
config_file: pubspec.pubspec_yaml,
99+
...res,
100+
};
101+
}
102+
}
103+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { locatePubspec } from "../index";
2+
import path from "path";
3+
test("find grida project cwd", () => {
4+
const _ = locatePubspec(path.join(__dirname, "sub-dir-for-testing"));
5+
expect(_.manifest.name).toBe("pubtest");
6+
});

cli/pub/__test__/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
name: pubtest

cli/pub/__test__/sub-dir-for-testing/.gitkeep

Whitespace-only changes.

cli/pub/index.ts

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,56 @@
1-
export function findPubSpec() {}
1+
import path from "path";
2+
import { find_in_cwd, find_in_parent } from "../_utils/path";
3+
import YAML from "yaml";
4+
import fs from "fs";
5+
6+
const _PUBSPEC_YAML = "pubspec.y{,a}ml";
7+
8+
interface IPubSpecManifest {
9+
name: string;
10+
description?: string;
11+
dependencies?: { [key: string]: string };
12+
}
13+
14+
interface PubspecSearchResult {
15+
base_dir: string;
16+
pubspec_yaml: string;
17+
manifest: IPubSpecManifest;
18+
}
19+
20+
export function locatePubspec(cwd = process.cwd()): PubspecSearchResult | null {
21+
const pubspecyaml = find_in_cwd(_PUBSPEC_YAML, cwd, true);
22+
if (pubspecyaml) {
23+
return {
24+
base_dir: path.dirname(pubspecyaml),
25+
pubspec_yaml: pubspecyaml,
26+
manifest: read(pubspecyaml),
27+
};
28+
}
29+
const pubspecyaml_in_parent_dir = find_in_parent(
30+
_PUBSPEC_YAML,
31+
cwd,
32+
true,
33+
true
34+
);
35+
if (pubspecyaml_in_parent_dir) {
36+
return {
37+
base_dir: path.dirname(pubspecyaml_in_parent_dir),
38+
pubspec_yaml: pubspecyaml_in_parent_dir,
39+
manifest: read(path.join(pubspecyaml_in_parent_dir)),
40+
};
41+
}
42+
return null;
43+
}
44+
45+
export function read(pubspec: string): IPubSpecManifest {
46+
return YAML.parse(fs.readFileSync(pubspec, "utf8"));
47+
}
48+
49+
export function analyzeFramework(pubspec: IPubSpecManifest): {
50+
framework: "flutter";
51+
} {
52+
const isflutter = "flutter" in pubspec || pubspec.dependencies?.flutter;
53+
if (isflutter) {
54+
return { framework: "flutter" };
55+
}
56+
}

0 commit comments

Comments
 (0)