@dbx-tools/cli 0.1.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/.projen/deps.json +43 -0
- package/.projen/files.json +10 -0
- package/.projen/tasks.json +121 -0
- package/README.md +74 -0
- package/bin/dbxtools.ts +10 -0
- package/index.ts +8 -0
- package/package.json +55 -0
- package/src/bootstrap.ts +67 -0
- package/src/cli.ts +34 -0
- package/src/pnpm.ts +60 -0
- package/src/root.ts +63 -0
- package/test/tsconfig.json +14 -0
- package/tsconfig.json +43 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": [
|
|
3
|
+
{
|
|
4
|
+
"name": "@types/node",
|
|
5
|
+
"version": "catalog:",
|
|
6
|
+
"type": "build"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "tsx",
|
|
10
|
+
"version": "^4.23.0",
|
|
11
|
+
"type": "build"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "typescript",
|
|
15
|
+
"type": "build"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "@clack/prompts",
|
|
19
|
+
"version": "catalog:",
|
|
20
|
+
"type": "runtime"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "@dbx-tools/core",
|
|
24
|
+
"version": "workspace:*",
|
|
25
|
+
"type": "runtime"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "@dbx-tools/shared-core",
|
|
29
|
+
"version": "workspace:*",
|
|
30
|
+
"type": "runtime"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "commander",
|
|
34
|
+
"version": "catalog:",
|
|
35
|
+
"type": "runtime"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "pnpm",
|
|
39
|
+
"type": "runtime"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm exec projen\"."
|
|
43
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifestVersion": 3,
|
|
3
|
+
"env": {
|
|
4
|
+
"PATH": "$(pnpm -c exec \"node --print process.env.PATH\")"
|
|
5
|
+
},
|
|
6
|
+
"tasks": {
|
|
7
|
+
"build": {
|
|
8
|
+
"name": "build",
|
|
9
|
+
"description": "Full release build",
|
|
10
|
+
"steps": [
|
|
11
|
+
{
|
|
12
|
+
"spawn": "pre-compile"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"spawn": "compile"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"spawn": "post-compile"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"spawn": "test"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"spawn": "package"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"compile": {
|
|
29
|
+
"name": "compile",
|
|
30
|
+
"description": "Only compile",
|
|
31
|
+
"steps": [
|
|
32
|
+
{
|
|
33
|
+
"execArgs": [
|
|
34
|
+
"tsc",
|
|
35
|
+
"--build"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"default": {
|
|
41
|
+
"name": "default",
|
|
42
|
+
"description": "Synthesize project files",
|
|
43
|
+
"steps": [
|
|
44
|
+
{
|
|
45
|
+
"exec": "pnpm exec projen default",
|
|
46
|
+
"cwd": "../../.."
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"install": {
|
|
51
|
+
"name": "install",
|
|
52
|
+
"description": "Install project dependencies and update lockfile (non-frozen)",
|
|
53
|
+
"steps": [
|
|
54
|
+
{
|
|
55
|
+
"exec": "pnpm i --no-frozen-lockfile"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"install:ci": {
|
|
60
|
+
"name": "install:ci",
|
|
61
|
+
"description": "Install project dependencies using frozen lockfile",
|
|
62
|
+
"steps": [
|
|
63
|
+
{
|
|
64
|
+
"exec": "pnpm i --frozen-lockfile"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"package": {
|
|
69
|
+
"name": "package",
|
|
70
|
+
"description": "Creates the distribution package",
|
|
71
|
+
"steps": [
|
|
72
|
+
{
|
|
73
|
+
"execArgs": [
|
|
74
|
+
"mkdir",
|
|
75
|
+
"-p",
|
|
76
|
+
"dist/js"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"execArgs": [
|
|
81
|
+
"pnpm",
|
|
82
|
+
"pack",
|
|
83
|
+
"--pack-destination",
|
|
84
|
+
"dist/js"
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
"post-compile": {
|
|
90
|
+
"name": "post-compile",
|
|
91
|
+
"description": "Runs after successful compilation"
|
|
92
|
+
},
|
|
93
|
+
"pre-compile": {
|
|
94
|
+
"name": "pre-compile",
|
|
95
|
+
"description": "Prepare the project for compilation"
|
|
96
|
+
},
|
|
97
|
+
"test": {
|
|
98
|
+
"name": "test",
|
|
99
|
+
"description": "Run tests",
|
|
100
|
+
"steps": [
|
|
101
|
+
{
|
|
102
|
+
"exec": "tsx --test 'test/**/*.test.ts'"
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"watch": {
|
|
107
|
+
"name": "watch",
|
|
108
|
+
"description": "Watch & compile in the background",
|
|
109
|
+
"steps": [
|
|
110
|
+
{
|
|
111
|
+
"execArgs": [
|
|
112
|
+
"tsc",
|
|
113
|
+
"--build",
|
|
114
|
+
"-w"
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm exec projen\"."
|
|
121
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# dbx-tools
|
|
2
|
+
|
|
3
|
+
CLI package for the dbx-tools projen workspace engine.
|
|
4
|
+
|
|
5
|
+
Run the `dbxtools` command to bootstrap a repo, synthesize generated files,
|
|
6
|
+
rebuild barrels, generate OpenAPI clients, or clean generated output. Import the
|
|
7
|
+
package modules when custom tooling needs the same root detection, pnpm
|
|
8
|
+
delegation, or CLI program behavior.
|
|
9
|
+
|
|
10
|
+
Key features:
|
|
11
|
+
|
|
12
|
+
- `sync` bootstrap path for empty folders plus normal projen synthesis for
|
|
13
|
+
existing workspaces.
|
|
14
|
+
- Focused `--watch` loop for projenrc changes, barrel generation, and OpenAPI
|
|
15
|
+
generation.
|
|
16
|
+
- Standalone barrel and OpenAPI commands for post-synth workflows.
|
|
17
|
+
- Generated-file cleanup with an interactive or non-interactive mode.
|
|
18
|
+
- Importable CLI/root/pnpm helpers for tests and thin wrapper commands.
|
|
19
|
+
|
|
20
|
+
## Bootstrap Or Sync A Workspace
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
dbxtools sync
|
|
24
|
+
dbxtools sync --watch
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
In an empty folder, `sync` creates the minimum pnpm/projen structure needed for
|
|
28
|
+
`@dbx-tools/projen`. In an existing workspace, it runs projen and the post-synth
|
|
29
|
+
generators. `--watch` starts focused watchers for structural changes, barrels,
|
|
30
|
+
and OpenAPI generation.
|
|
31
|
+
|
|
32
|
+
## Generate Barrels And OpenAPI Clients
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
dbxtools barrels
|
|
36
|
+
dbxtools openapi
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`barrels` rebuilds package-root `index.ts` files from exported modules under
|
|
40
|
+
`src/`. `openapi` scans tsoa controllers and writes generated OpenAPI packages.
|
|
41
|
+
|
|
42
|
+
## Clean Generated Output
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
dbxtools clean
|
|
46
|
+
dbxtools clean -y
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`clean` removes generated read-only files and can also remove install output. Use
|
|
50
|
+
it before debugging synthesis drift or validating that the repo can regenerate
|
|
51
|
+
from source.
|
|
52
|
+
|
|
53
|
+
## Use The CLI Internals
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { cli, root, pnpm } from "dbx-tools";
|
|
57
|
+
|
|
58
|
+
await cli.runCli(["sync"]);
|
|
59
|
+
const workspaceRoot = await root.findWorkspaceRoot();
|
|
60
|
+
pnpm.runProjen(["barrels"], workspaceRoot);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Importing internals is mainly useful for tests or wrapper scripts; most users
|
|
64
|
+
should run the `dbxtools` bin.
|
|
65
|
+
|
|
66
|
+
## Modules
|
|
67
|
+
|
|
68
|
+
- `cli` - Commander entrypoint and `runCli()`.
|
|
69
|
+
- `bootstrap` - empty-workspace bootstrap.
|
|
70
|
+
- `root` - workspace-root detection and bootstrap/install checks.
|
|
71
|
+
- `pnpm` - pnpm/projen command resolution and delegation.
|
|
72
|
+
|
|
73
|
+
The reusable project classes and generators live in
|
|
74
|
+
[`@dbx-tools/projen`](../../node/projen).
|
package/bin/dbxtools.ts
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// GENERATED by projen watch - DO NOT EDIT.
|
|
2
|
+
// Regenerated from the exporting modules in ./src.
|
|
3
|
+
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
|
+
|
|
5
|
+
export * as bootstrap from "./src/bootstrap";
|
|
6
|
+
export * as cli from "./src/cli";
|
|
7
|
+
export * as pnpm from "./src/pnpm";
|
|
8
|
+
export * as root from "./src/root";
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dbx-tools/cli",
|
|
3
|
+
"repository": {
|
|
4
|
+
"type": "git",
|
|
5
|
+
"url": "git+https://github.com/reggie-db/dbx-tools.git",
|
|
6
|
+
"directory": "workspaces/cli/dbx-tools"
|
|
7
|
+
},
|
|
8
|
+
"bin": {
|
|
9
|
+
"dbxtools": "./bin/dbxtools.ts",
|
|
10
|
+
"dbxtools.ts": "bin/dbxtools.ts"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/node": "^24.6.0",
|
|
14
|
+
"tsx": "^4.23.0",
|
|
15
|
+
"typescript": "^5.9.3"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@clack/prompts": "^1.7.0",
|
|
19
|
+
"commander": "^15.0.0",
|
|
20
|
+
"pnpm": "^11.0.6",
|
|
21
|
+
"@dbx-tools/core": "0.1.9",
|
|
22
|
+
"@dbx-tools/shared-core": "0.1.9"
|
|
23
|
+
},
|
|
24
|
+
"main": "index.ts",
|
|
25
|
+
"license": "UNLICENSED",
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public",
|
|
28
|
+
"provenance": true
|
|
29
|
+
},
|
|
30
|
+
"version": "0.1.9",
|
|
31
|
+
"types": "index.ts",
|
|
32
|
+
"type": "module",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": "./index.ts",
|
|
35
|
+
"./pnpm": "./src/pnpm.ts",
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"dbxToolsConfig": {
|
|
39
|
+
"tags": [
|
|
40
|
+
"cli"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm exec projen\".",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "projen build",
|
|
46
|
+
"compile": "projen compile",
|
|
47
|
+
"default": "projen default",
|
|
48
|
+
"package": "projen package",
|
|
49
|
+
"post-compile": "projen post-compile",
|
|
50
|
+
"pre-compile": "projen pre-compile",
|
|
51
|
+
"test": "projen test",
|
|
52
|
+
"watch": "projen watch",
|
|
53
|
+
"projen": "projen"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/bootstrap.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstrap a brand-new folder into a working dbx-tools workspace before projen runs.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { intro, outro } from "@clack/prompts";
|
|
7
|
+
import { exec } from "@dbx-tools/core";
|
|
8
|
+
import { resolvePnpmArgv, runPnpm } from "./pnpm";
|
|
9
|
+
import { rootLabel } from "./root";
|
|
10
|
+
|
|
11
|
+
const DEFAULT_PROJEN_SPECIFIER = "@dbx-tools/projen";
|
|
12
|
+
|
|
13
|
+
const PROJENRC_TEMPLATE = `import { DBXToolsNodeProject } from "@dbx-tools/projen";
|
|
14
|
+
|
|
15
|
+
const project = new DBXToolsNodeProject();
|
|
16
|
+
project.synth();
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
/** Seed `pnpm-workspace.yaml` so the first \`pnpm add\` can allow esbuild non-interactively. */
|
|
20
|
+
const WORKSPACE_SEED = `packages: []
|
|
21
|
+
allowBuilds:
|
|
22
|
+
esbuild: true
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Turn an empty folder into a functioning dbx-tools workspace: `pnpm init`, seed
|
|
27
|
+
* `pnpm-workspace.yaml`, add `projen`/`typescript`/`tsx` + the engine package,
|
|
28
|
+
* write a minimal `.projenrc.ts`, synth once (with `PROJEN_DISABLE_POST`), then
|
|
29
|
+
* install. Does not run barrels - run `dbxtools barrels` or a full projen synth
|
|
30
|
+
* post-install to generate package barrels.
|
|
31
|
+
*/
|
|
32
|
+
export function bootstrapWorkspace(
|
|
33
|
+
root: string,
|
|
34
|
+
projenSpecifier: string = DEFAULT_PROJEN_SPECIFIER,
|
|
35
|
+
): void {
|
|
36
|
+
intro(`Bootstrapping dbx-tools workspace in ${rootLabel(root)}`);
|
|
37
|
+
|
|
38
|
+
if (!existsSync(join(root, "package.json"))) {
|
|
39
|
+
runPnpm(["init"], root);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const workspaceFile = join(root, "pnpm-workspace.yaml");
|
|
43
|
+
if (!existsSync(workspaceFile)) {
|
|
44
|
+
writeFileSync(workspaceFile, WORKSPACE_SEED);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
runPnpm(["add", "-D", "projen", "typescript@^5.9.3", "tsx@^4.23.0", projenSpecifier], root);
|
|
48
|
+
|
|
49
|
+
const projenrc = join(root, ".projenrc.ts");
|
|
50
|
+
if (!existsSync(projenrc)) {
|
|
51
|
+
writeFileSync(projenrc, PROJENRC_TEMPLATE);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
runSynth(root);
|
|
55
|
+
|
|
56
|
+
runPnpm(["install", "--no-frozen-lockfile", "--force"], root);
|
|
57
|
+
outro("Workspace ready - re-run dbxtools or add packages under workspaces/");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function runSynth(root: string): void {
|
|
61
|
+
const [command, ...prefix] = resolvePnpmArgv();
|
|
62
|
+
exec.spawnSync(command, [...prefix, "exec", "tsx", ".projenrc.ts"], {
|
|
63
|
+
cwd: root,
|
|
64
|
+
env: { ...process.env, PROJEN_DISABLE_POST: "true" },
|
|
65
|
+
check: true,
|
|
66
|
+
});
|
|
67
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dbxtools` commander entry: detect root, bootstrap or install, forward to projen.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { bootstrapWorkspace } from "./bootstrap";
|
|
6
|
+
import { ensureWorkspaceReady, runProjen } from "./pnpm";
|
|
7
|
+
import { findWorkspaceRoot, needsBootstrap } from "./root";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Prepare the workspace at `root`, then run `pnpm exec projen` with `projenArgs`.
|
|
11
|
+
*/
|
|
12
|
+
async function prepareAndRunProjen(projenArgs: string[], startDir?: string): Promise<void> {
|
|
13
|
+
const root = await findWorkspaceRoot(startDir);
|
|
14
|
+
if (needsBootstrap(root)) {
|
|
15
|
+
bootstrapWorkspace(root);
|
|
16
|
+
} else {
|
|
17
|
+
ensureWorkspaceReady(root);
|
|
18
|
+
}
|
|
19
|
+
runProjen(projenArgs, root);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Parse `argv` with commander and forward remaining args to projen. */
|
|
23
|
+
export async function runCli(argv: string[]): Promise<void> {
|
|
24
|
+
const program = new Command()
|
|
25
|
+
.name("dbxtools")
|
|
26
|
+
.description("Bootstrap dbx-tools workspaces and forward to projen")
|
|
27
|
+
.allowUnknownOption()
|
|
28
|
+
.allowExcessArguments()
|
|
29
|
+
.showHelpAfterError()
|
|
30
|
+
.helpOption("-h, --help", "Show dbxtools help");
|
|
31
|
+
|
|
32
|
+
program.parse(argv);
|
|
33
|
+
await prepareAndRunProjen(program.args);
|
|
34
|
+
}
|
package/src/pnpm.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pnpm discovery, workspace install, and projen forwarding for the `dbxtools` CLI.
|
|
3
|
+
*/
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { exec } from "@dbx-tools/core";
|
|
7
|
+
import { functionModule } from "@dbx-tools/shared-core";
|
|
8
|
+
import { needsInstall } from "./root";
|
|
9
|
+
|
|
10
|
+
/** A package.json `bin` field: either a single command string, or a name -> path map. */
|
|
11
|
+
type BinField = string | Record<string, string>;
|
|
12
|
+
|
|
13
|
+
function resolvePnpmArgvImpl(): string[] {
|
|
14
|
+
try {
|
|
15
|
+
const require = createRequire(import.meta.url);
|
|
16
|
+
const pkgJsonPath = require.resolve("pnpm/package.json");
|
|
17
|
+
const pkg = require(pkgJsonPath) as { bin: BinField };
|
|
18
|
+
const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin.pnpm;
|
|
19
|
+
return [process.execPath, join(dirname(pkgJsonPath), bin)];
|
|
20
|
+
} catch {
|
|
21
|
+
try {
|
|
22
|
+
exec.spawnSync("corepack", ["enable", "pnpm"], {
|
|
23
|
+
stderr: "ignore",
|
|
24
|
+
stdin: "ignore",
|
|
25
|
+
stdout: "ignore",
|
|
26
|
+
check: true,
|
|
27
|
+
});
|
|
28
|
+
exec.spawnSync("pnpm", ["--version"], {
|
|
29
|
+
stderr: "ignore",
|
|
30
|
+
stdin: "ignore",
|
|
31
|
+
stdout: "ignore",
|
|
32
|
+
check: true,
|
|
33
|
+
});
|
|
34
|
+
return ["pnpm"];
|
|
35
|
+
} catch {
|
|
36
|
+
return ["npx", "-y", "pnpm"];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Memoized `[command, ...prefix]` argv prefix to run pnpm (resolved install, else corepack, else npx). */
|
|
42
|
+
export const resolvePnpmArgv = functionModule.memoize(resolvePnpmArgvImpl);
|
|
43
|
+
|
|
44
|
+
/** Run pnpm with inherited stdio from `cwd`. */
|
|
45
|
+
export function runPnpm(args: string[], cwd: string): void {
|
|
46
|
+
const [command, ...prefix] = resolvePnpmArgv();
|
|
47
|
+
exec.spawnSync(command, [...prefix, ...args], { cwd, check: true });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Install workspace dependencies when `node_modules` or projen is missing. */
|
|
51
|
+
export function ensureWorkspaceReady(root: string): void {
|
|
52
|
+
if (needsInstall(root)) {
|
|
53
|
+
runPnpm(["install", "--no-frozen-lockfile"], root);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Run `pnpm exec projen` with the given args from `root`. */
|
|
58
|
+
export function runProjen(args: string[], root: string): void {
|
|
59
|
+
runPnpm(["exec", "projen", ...args], root);
|
|
60
|
+
}
|
package/src/root.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace root detection for the `dbxtools` CLI.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
6
|
+
import { exec } from "@dbx-tools/core";
|
|
7
|
+
import { functionModule } from "@dbx-tools/shared-core";
|
|
8
|
+
|
|
9
|
+
async function gitToplevel(): Promise<string | undefined> {
|
|
10
|
+
const { exitCode, stdout } = await exec.spawn("git", ["rev-parse", "--show-toplevel"], {
|
|
11
|
+
stdout: "capture",
|
|
12
|
+
stderr: "ignore",
|
|
13
|
+
stdin: "ignore",
|
|
14
|
+
});
|
|
15
|
+
if (exitCode !== 0) return undefined;
|
|
16
|
+
return stdout || undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Walk upward from `startDir` for `.projenrc.ts`. If none is found, try git
|
|
21
|
+
* top-level only when that directory also contains `.projenrc.ts`; otherwise return
|
|
22
|
+
* `resolve(startDir)` (which may not be a workspace root).
|
|
23
|
+
*/
|
|
24
|
+
export async function findWorkspaceRoot(startDir: string = process.cwd()): Promise<string> {
|
|
25
|
+
let dir = resolve(startDir);
|
|
26
|
+
while (true) {
|
|
27
|
+
if (existsSync(join(dir, ".projenrc.ts"))) return dir;
|
|
28
|
+
const parent = dirname(dir);
|
|
29
|
+
if (parent === dir) break;
|
|
30
|
+
dir = parent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const fromGit = await gitToplevel();
|
|
34
|
+
if (fromGit && existsSync(join(fromGit, ".projenrc.ts"))) return fromGit;
|
|
35
|
+
|
|
36
|
+
return resolve(startDir);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* True when the folder has no `.projenrc.ts` yet and needs full bootstrapping.
|
|
41
|
+
* Keying off `.projenrc.ts` (not `package.json`) avoids clobbering a cleaned
|
|
42
|
+
* workspace that still has a hand-authored projenrc.
|
|
43
|
+
*/
|
|
44
|
+
export function needsBootstrap(root: string): boolean {
|
|
45
|
+
return !existsSync(join(root, ".projenrc.ts"));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** True when `node_modules` or projen itself is missing under `root`. */
|
|
49
|
+
export function needsInstall(root: string): boolean {
|
|
50
|
+
if (!existsSync(join(root, "node_modules"))) return true;
|
|
51
|
+
if (existsSync(join(root, ".projenrc.ts")) && !existsSync(join(root, "node_modules", "projen"))) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Async, memoized root lookup from the process cwd at first use. */
|
|
58
|
+
export const workspaceRoot = functionModule.memoize(() => findWorkspaceRoot());
|
|
59
|
+
|
|
60
|
+
/** Short label for log output (`basename` of the resolved root). */
|
|
61
|
+
export function rootLabel(root: string): string {
|
|
62
|
+
return basename(root) || root;
|
|
63
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// ~~ Generated by projen. To modify, edit .projenrc.js and run "pnpm exec projen".
|
|
2
|
+
{
|
|
3
|
+
"extends": "../tsconfig.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"noEmit": true,
|
|
6
|
+
"rootDir": ".."
|
|
7
|
+
},
|
|
8
|
+
"include": [
|
|
9
|
+
"**/*.ts"
|
|
10
|
+
],
|
|
11
|
+
"exclude": [
|
|
12
|
+
"node_modules"
|
|
13
|
+
]
|
|
14
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// ~~ Generated by projen. To modify, edit .projenrc.js and run "pnpm exec projen".
|
|
2
|
+
{
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": ".",
|
|
5
|
+
"outDir": "lib",
|
|
6
|
+
"alwaysStrict": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"inlineSourceMap": true,
|
|
11
|
+
"inlineSources": true,
|
|
12
|
+
"lib": [
|
|
13
|
+
"ES2022"
|
|
14
|
+
],
|
|
15
|
+
"module": "ESNext",
|
|
16
|
+
"noEmitOnError": false,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitAny": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noImplicitThis": true,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"resolveJsonModule": true,
|
|
24
|
+
"strict": true,
|
|
25
|
+
"strictNullChecks": true,
|
|
26
|
+
"strictPropertyInitialization": true,
|
|
27
|
+
"stripInternal": true,
|
|
28
|
+
"target": "ES2022",
|
|
29
|
+
"types": [
|
|
30
|
+
"node"
|
|
31
|
+
],
|
|
32
|
+
"moduleResolution": "bundler",
|
|
33
|
+
"skipLibCheck": true
|
|
34
|
+
},
|
|
35
|
+
"include": [
|
|
36
|
+
"src/**/*.ts",
|
|
37
|
+
"index.ts",
|
|
38
|
+
"bin/**/*.ts"
|
|
39
|
+
],
|
|
40
|
+
"exclude": [
|
|
41
|
+
"node_modules"
|
|
42
|
+
]
|
|
43
|
+
}
|