@dbx-tools/core 0.6.89 → 0.6.91
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/README.md +68 -12
- package/index.ts +4 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +4 -2
- package/lib/src/bundle.d.ts +38 -0
- package/lib/src/bundle.js +177 -0
- package/lib/src/config.d.ts +53 -30
- package/lib/src/config.js +269 -98
- package/lib/src/file.d.ts +8 -0
- package/lib/src/file.js +16 -1
- package/lib/src/project.d.ts +7 -4
- package/lib/src/project.js +52 -35
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/bundle.ts +211 -0
- package/src/config.ts +296 -122
- package/src/file.ts +19 -0
- package/src/project.ts +57 -42
package/src/project.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { Stats, readFileSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { json, net, string } from "@dbx-tools/shared-core";
|
|
5
5
|
import { statSync as fileStatSync } from "./file.ts";
|
|
6
6
|
|
|
7
7
|
const ROOT_MARKERS = [
|
|
@@ -12,9 +12,13 @@ const ROOT_MARKERS = [
|
|
|
12
12
|
"package.json",
|
|
13
13
|
] as const;
|
|
14
14
|
|
|
15
|
+
/** Resolve a blank, null, omitted, relative, or absolute cwd to an absolute path. */
|
|
16
|
+
export function resolveWorkingDirectory(cwd?: string | null): string {
|
|
17
|
+
return resolve(string.trimToNull(cwd) ?? process.cwd());
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
/** A command's stdout, classified as a filesystem path and/or a URL. */
|
|
16
21
|
export interface ProjectContext {
|
|
17
|
-
readonly cwd: string;
|
|
18
22
|
readonly output: string;
|
|
19
23
|
/** `output` when it names something on disk. */
|
|
20
24
|
readonly path?: string;
|
|
@@ -46,48 +50,50 @@ function projectContextCommandOutput(command: string, args: string[], cwd: strin
|
|
|
46
50
|
// `http://localhost/…`), which would mislabel directory outputs and bare
|
|
47
51
|
// tokens - so gate on the raw output already carrying a scheme + authority.
|
|
48
52
|
const url = /^[a-z][a-z0-9+.-]*:\/\//i.test(output) ? net.urlBuilder(output) : undefined;
|
|
49
|
-
return {
|
|
53
|
+
return { output, path: pathStats ? output : undefined, pathStats, url };
|
|
50
54
|
}
|
|
51
|
-
return {
|
|
55
|
+
return { output };
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
* These commands (`npm prefix`, `git rev-parse`, `gh repo view`) are pure
|
|
58
|
-
* functions of the directory they run in, so their output is worth keeping - but
|
|
59
|
-
* only while the process is still IN that directory. {@link context.cached}
|
|
60
|
-
* owns that rule: the slot remembers the `cwd` it was loaded under and misses
|
|
61
|
-
* once the process moves, and a lookup for some OTHER directory runs the command
|
|
62
|
-
* without caching, so it can't evict the hot entry. The slot name carries the
|
|
63
|
-
* command and its arguments (order-sensitive), so two commands never share one.
|
|
64
|
-
*/
|
|
58
|
+
const projectCommandCache = new Map<string, ProjectContext>();
|
|
59
|
+
|
|
65
60
|
function projectContextCommand(command: string, args: string[], cwd?: string): ProjectContext {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
(
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
62
|
+
const key =
|
|
63
|
+
resolved === resolveWorkingDirectory() ? JSON.stringify([command, ...args]) : undefined;
|
|
64
|
+
if (key !== undefined) {
|
|
65
|
+
const cached = projectCommandCache.get(key);
|
|
66
|
+
if (cached !== undefined) return cached;
|
|
67
|
+
}
|
|
68
|
+
const value = projectContextCommandOutput(command, args, resolved);
|
|
69
|
+
if (key !== undefined) projectCommandCache.set(key, value);
|
|
70
|
+
return value;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
function
|
|
74
|
-
const parsed = projectContextCommand(
|
|
73
|
+
function commandRoot(command: string, args: string[], cwd: string): string | undefined {
|
|
74
|
+
const parsed = projectContextCommand(command, args, cwd);
|
|
75
75
|
return parsed.pathStats?.isDirectory() ? parsed.path : undefined;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
function npmRoot(cwd?: string): string | undefined {
|
|
79
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
80
|
+
return commandRoot("npm", ["prefix"], resolved);
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
function gitRoot(cwd?: string): string | undefined {
|
|
79
|
-
const
|
|
80
|
-
return
|
|
84
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
85
|
+
return commandRoot("git", ["rev-parse", "--show-toplevel"], resolved);
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
export function root(cwd
|
|
84
|
-
|
|
88
|
+
export function root(cwd?: string): string | undefined {
|
|
89
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
90
|
+
let current = resolved;
|
|
85
91
|
|
|
86
92
|
if (!fileStatSync(current)?.isDirectory()) {
|
|
87
93
|
current = dirname(current);
|
|
88
94
|
}
|
|
89
95
|
const boundaries = new Set(
|
|
90
|
-
[npmRoot(
|
|
96
|
+
[npmRoot(resolved), gitRoot(resolved)]
|
|
91
97
|
.filter((path): path is string => path !== undefined)
|
|
92
98
|
.map((path) => resolve(path)),
|
|
93
99
|
);
|
|
@@ -152,8 +158,8 @@ function lastPathSegment(path: string): string {
|
|
|
152
158
|
* `npm prefix`, the git top-level, then `cwd` itself. Duplicates are skipped;
|
|
153
159
|
* only existing directories are yielded (except the final `cwd` fallback).
|
|
154
160
|
*/
|
|
155
|
-
export function* resolveProjectRoots(cwd
|
|
156
|
-
const base =
|
|
161
|
+
export function* resolveProjectRoots(cwd?: string): Generator<string> {
|
|
162
|
+
const base = resolveWorkingDirectory(cwd);
|
|
157
163
|
const seen = new Set<string>();
|
|
158
164
|
for (const candidate of [npmRoot(base), gitRoot(base)]) {
|
|
159
165
|
if (!candidate) continue;
|
|
@@ -166,13 +172,13 @@ export function* resolveProjectRoots(cwd: string = process.cwd()): Generator<str
|
|
|
166
172
|
}
|
|
167
173
|
|
|
168
174
|
/** The nearest ancestor of `cwd` (from {@link resolveProjectRoots}) with a `package.json`. */
|
|
169
|
-
function workspaceRoot(cwd
|
|
175
|
+
function workspaceRoot(cwd?: string): string {
|
|
170
176
|
let last: string | undefined;
|
|
171
177
|
for (const dir of resolveProjectRoots(cwd)) {
|
|
172
178
|
if (fileStatSync(resolve(dir, "package.json"))?.isFile()) return dir;
|
|
173
179
|
last = dir;
|
|
174
180
|
}
|
|
175
|
-
return last ??
|
|
181
|
+
return last ?? resolveWorkingDirectory(cwd);
|
|
176
182
|
}
|
|
177
183
|
|
|
178
184
|
/**
|
|
@@ -180,8 +186,9 @@ function workspaceRoot(cwd: string = process.cwd()): string {
|
|
|
180
186
|
* `package.json` `name`, then the git remote's repo name, then the root
|
|
181
187
|
* directory's basename.
|
|
182
188
|
*/
|
|
183
|
-
export function name(cwd
|
|
184
|
-
const
|
|
189
|
+
export function name(cwd?: string): string {
|
|
190
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
191
|
+
const rootDir = workspaceRoot(resolved);
|
|
185
192
|
|
|
186
193
|
const fromPackage = readPackageName(resolve(rootDir, "package.json"));
|
|
187
194
|
if (fromPackage) return fromPackage;
|
|
@@ -252,19 +259,17 @@ function repositoryUrlFromGit(cwd?: string): string | undefined {
|
|
|
252
259
|
/**
|
|
253
260
|
* The repo's canonical remote URL, or `undefined` when there is no git remote.
|
|
254
261
|
* Tries `gh repo view` first (host-accurate, no parsing), then normalizes
|
|
255
|
-
* `git remote get-url origin`.
|
|
256
|
-
*
|
|
262
|
+
* `git remote get-url origin`. A blank, omitted, or explicitly current `cwd`
|
|
263
|
+
* reuses cached command probes; another resolved directory executes directly.
|
|
257
264
|
*
|
|
258
265
|
* @param cwd - directory to resolve from (defaults to `process.cwd()`).
|
|
259
266
|
* @param format - `"https"` (default) yields `https://host/owner/repo`;
|
|
260
267
|
* `"npm"` yields npm's `git+https://host/owner/repo.git` form (for a
|
|
261
268
|
* `package.json` `repository.url` that passes npm provenance).
|
|
262
269
|
*/
|
|
263
|
-
export function repositoryUrl(
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
): string | undefined {
|
|
267
|
-
const https = repositoryUrlFromGh(cwd) ?? repositoryUrlFromGit(cwd);
|
|
270
|
+
export function repositoryUrl(cwd?: string, format: "https" | "npm" = "https"): string | undefined {
|
|
271
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
272
|
+
const https = repositoryUrlFromGh(resolved) ?? repositoryUrlFromGit(resolved);
|
|
268
273
|
if (!https) return undefined;
|
|
269
274
|
return format === "npm" ? `git+${https.replace(/\.git$/, "")}.git` : https;
|
|
270
275
|
}
|
|
@@ -272,11 +277,21 @@ export function repositoryUrl(
|
|
|
272
277
|
/**
|
|
273
278
|
* The active npm registry (`npm config get registry`) as a chainable
|
|
274
279
|
* {@link net.UrlBuilder}, or `undefined` when npm is absent or prints no URL.
|
|
275
|
-
*
|
|
280
|
+
* A blank, null, omitted, or explicitly current `cwd` reuses the cached npm
|
|
281
|
+
* command; another resolved directory executes it directly. Environment options
|
|
282
|
+
* are evaluated on every call.
|
|
276
283
|
*/
|
|
277
284
|
export function npmRegistry(
|
|
278
285
|
cwd?: string | null,
|
|
279
286
|
options?: { overrideOnly?: boolean; envVars?: boolean },
|
|
287
|
+
): net.UrlBuilder | undefined {
|
|
288
|
+
const resolved = resolveWorkingDirectory(cwd);
|
|
289
|
+
return resolveNpmRegistry(resolved, options);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function resolveNpmRegistry(
|
|
293
|
+
cwd: string | null | undefined,
|
|
294
|
+
options: { overrideOnly?: boolean; envVars?: boolean } | undefined,
|
|
280
295
|
): net.UrlBuilder | undefined {
|
|
281
296
|
const candidates = (function* () {
|
|
282
297
|
yield projectContextCommand(
|
|
@@ -321,5 +336,5 @@ if (import.meta.main) {
|
|
|
321
336
|
console.log("package root:", root());
|
|
322
337
|
console.log("project name:", name());
|
|
323
338
|
console.log("repository url:", repositoryUrl());
|
|
324
|
-
console.log("repository url (npm):", repositoryUrl(
|
|
339
|
+
console.log("repository url (npm):", repositoryUrl(undefined, "npm"));
|
|
325
340
|
}
|