@dbx-tools/projen 0.9.119 → 0.9.121
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 +15 -8
- package/index.ts +2 -2
- package/package.json +5 -5
- package/src/barrels.ts +3 -3
- package/src/clean.ts +18 -11
- package/src/dev-watch.ts +0 -5
- package/src/packages.ts +2 -2
- package/src/python-node-bindings.ts +1 -1
- package/src/shared-core-usage.ts +13 -7
- package/src/watch.ts +6 -6
- package/tasks/barrels.ts +1 -1
- package/tasks/clean.ts +1 -2
- package/tasks/compile-workspace.ts +4 -2
- package/tasks/dev-watch.ts +130 -48
- package/tasks/projenrc.ts +2 -2
- package/tasks/python-node-bindings-watch.ts +1 -1
- package/tasks/python-node-bindings.ts +2 -1
- package/tasks/python-node-runtime-watch.ts +1 -1
- package/tasks/release.ts +11 -11
- package/tasks/shared-core-usage.ts +2 -2
- package/tasks/sync.ts +2 -5
- package/tasks/version-check.ts +2 -2
package/README.md
CHANGED
|
@@ -508,19 +508,26 @@ bun run release --publish pypi --no-docs
|
|
|
508
508
|
bun run release --no-npm --no-local-publish
|
|
509
509
|
bun run release --publish local --install never
|
|
510
510
|
bun run release --local-registry false --local-pypi auto
|
|
511
|
-
bun run release --demo-deploy
|
|
511
|
+
bun run release --demo-deploy --profile FEVM-REGGIE-PIERCE-AWS
|
|
512
512
|
bun run release --no-release-notes
|
|
513
513
|
bun run release --release-notes-text "# Release 1.2.3"
|
|
514
514
|
bun run release --release-notes-file ./notes.md
|
|
515
515
|
bun run release --release-notes-instructions "Focus on operator-visible changes."
|
|
516
516
|
```
|
|
517
517
|
|
|
518
|
-
`--demo-deploy` is off by default
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
518
|
+
`--demo-deploy` is off by default. After tagging and any local registry
|
|
519
|
+
publication it runs `bun run demo:deploy`, which stages the AppKit demo from
|
|
520
|
+
locally compiled Node packages and locally built Python wheels, resolves
|
|
521
|
+
the default environment or configured credentials through
|
|
522
|
+
`@dbx-tools/auth`, including `DATABRICKS_CONFIG_PROFILE`, `DATABRICKS_HOST`,
|
|
523
|
+
and the other auth options, force-refreshes its token with interactive login
|
|
524
|
+
fallback, and deploys it. When auth selects a profile, the deploy passes that
|
|
525
|
+
resolved profile explicitly to every bundle command. That step is local only
|
|
526
|
+
and is not recorded in the annotated tag.
|
|
527
|
+
|
|
528
|
+
Pass `--profile <name>` to set `DATABRICKS_CONFIG_PROFILE` only for that local
|
|
529
|
+
demo deployment. The profile is not forwarded as a release subcommand
|
|
530
|
+
argument or stored in the release tag.
|
|
524
531
|
|
|
525
532
|
After bump and configured validation, release writes
|
|
526
533
|
`docs/releases/vX.Y.Z.md` with `dbx genie exec -C "$PWD" --sandbox read-only
|
|
@@ -618,7 +625,7 @@ release [options]
|
|
|
618
625
|
| `--release-notes-instructions <value>` | Append instructions to the Genie release-note prompt (env: PROJEN_RELEASE_RELEASE_NOTES_INSTRUCTIONS) |
|
|
619
626
|
| `--demo-deploy` | Deploy the AppKit demo after tagging and local publication (env: PROJEN_RELEASE_DEMO_DEPLOY) |
|
|
620
627
|
| `--no-demo-deploy` | Disable deploy the appkit demo after tagging and local publication |
|
|
621
|
-
| `--profile <value>` |
|
|
628
|
+
| `--profile <value>` | Databricks CLI profile for the optional demo deployment |
|
|
622
629
|
| `--local-publish` | Publish to configured local registries (default: true, env: PROJEN_RELEASE_LOCAL_PUBLISH) |
|
|
623
630
|
| `--no-local-publish` | Disable publish to configured local registries |
|
|
624
631
|
| `--local-registry <value>` | Local npm registry selection: auto, false, or URL (default: "auto", env: PROJEN_RELEASE_LOCAL_REGISTRY) |
|
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/projen";
|
|
6
|
-
export const PACKAGE_VERSION = "0.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.121";
|
|
7
7
|
export * as barrels from "./src/barrels.ts";
|
|
8
8
|
export * as bunApp from "./src/bun-app.ts";
|
|
9
9
|
export * as bunWorkflow from "./src/bun-workflow.ts";
|
|
@@ -41,7 +41,7 @@ export { BUN_DEV_OVERRIDE, BUN_BUILD_OVERRIDE, BUN_APP_OVERRIDES, RootBunfigFile
|
|
|
41
41
|
export { BUN_VERSION } from "./src/bun-workflow.ts";
|
|
42
42
|
export { DBXToolsConfigDataSchema, DBXToolsConfig } from "./src/dbx-tools-config.ts";
|
|
43
43
|
export type { DBXToolsConfigOptions, DBXToolsConfigData } from "./src/dbx-tools-config.ts";
|
|
44
|
-
export { DEV_WATCH_TASK, DEV_WATCH_SCRIPT, DEV_RESTART_DEBOUNCE_MS, DEV_RESTART_KEY
|
|
44
|
+
export { DEV_WATCH_TASK, DEV_WATCH_SCRIPT, DEV_RESTART_DEBOUNCE_MS, DEV_RESTART_KEY } from "./src/dev-watch.ts";
|
|
45
45
|
export { resolvePkgRoot } from "./src/engine-root.ts";
|
|
46
46
|
export { PYTHON_GENERATED_PACKAGE, PYTHON_SYNC_PACKAGE } from "./src/generated.ts";
|
|
47
47
|
export type { HeaderOpts } from "./src/generated.ts";
|
package/package.json
CHANGED
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@clack/prompts": "^1.7.0",
|
|
33
|
-
"@dbx-tools/cli-args": "^0.9.
|
|
34
|
-
"@dbx-tools/core": "^0.9.
|
|
35
|
-
"@dbx-tools/path": "^0.9.
|
|
36
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
33
|
+
"@dbx-tools/cli-args": "^0.9.121",
|
|
34
|
+
"@dbx-tools/core": "^0.9.121",
|
|
35
|
+
"@dbx-tools/path": "^0.9.121",
|
|
36
|
+
"@dbx-tools/shared-core": "^0.9.121",
|
|
37
37
|
"commander": "^15.0.0",
|
|
38
38
|
"concurrently": "^10.0.3",
|
|
39
39
|
"constructs": "^10.6.0",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"main": "index.ts",
|
|
57
57
|
"license": "Apache-2.0",
|
|
58
|
-
"version": "0.9.
|
|
58
|
+
"version": "0.9.121",
|
|
59
59
|
"types": "index.ts",
|
|
60
60
|
"type": "module",
|
|
61
61
|
"exports": {
|
package/src/barrels.ts
CHANGED
|
@@ -339,14 +339,14 @@ export function isGeneratedBarrel(file: string): boolean {
|
|
|
339
339
|
|
|
340
340
|
/** Public direct modules and child-directory facades for one generated barrel. */
|
|
341
341
|
function barrelCandidates(barrelDir: string): string[] {
|
|
342
|
-
const files = [...find.
|
|
342
|
+
const files = [...find.findFilesSync("*", { cwd: barrelDir })]
|
|
343
343
|
.map(toPosix)
|
|
344
344
|
.filter((file) => !file.includes("/"))
|
|
345
345
|
.filter((file) => file !== "index.ts" && file !== CUSTOM_EXPORTS_FILE)
|
|
346
346
|
.filter((file) => isModuleFile(file))
|
|
347
347
|
.filter((file) => !isExcluded(file, barrelDir))
|
|
348
348
|
.filter((file) => hasExport(join(barrelDir, file)));
|
|
349
|
-
const childIndexes = [...find.
|
|
349
|
+
const childIndexes = [...find.findFilesSync("*/index.ts", { cwd: barrelDir })]
|
|
350
350
|
.map(toPosix)
|
|
351
351
|
.filter((file) => file.split("/").length === 2)
|
|
352
352
|
.filter((file) => !isExcluded(file, barrelDir))
|
|
@@ -424,7 +424,7 @@ function generateForPackage(pkgDir: string): number {
|
|
|
424
424
|
const srcDir = join(pkgDir, "src");
|
|
425
425
|
if (!existsSync(srcDir)) return 0;
|
|
426
426
|
|
|
427
|
-
const sourceFiles = [...find.
|
|
427
|
+
const sourceFiles = [...find.findFilesSync("**/*", { cwd: srcDir })]
|
|
428
428
|
.map(toPosix)
|
|
429
429
|
.filter((file) => isModuleFile(file) || /(^|\/)index\.ts$/.test(file));
|
|
430
430
|
const manifest = json.parseRecord(readFileSync(join(pkgDir, "package.json"), "utf8"));
|
package/src/clean.ts
CHANGED
|
@@ -37,9 +37,9 @@ const CLEAN_SKIP_FILES: ReadonlySet<string> = new Set([".gitignore"]);
|
|
|
37
37
|
* ignores AND every dot-prefixed folder (`.projen`, `.vscode`, `.github`, ...), and
|
|
38
38
|
* {@link CLEAN_SKIP_FILES} entry (`.gitignore`).
|
|
39
39
|
*/
|
|
40
|
-
function nativeGeneratedFiles(root: string): string[] {
|
|
40
|
+
async function nativeGeneratedFiles(root: string): Promise<string[]> {
|
|
41
41
|
const files = new Set<string>();
|
|
42
|
-
for (const manifestPath of find.findFiles("**/.projen/files.json", {
|
|
42
|
+
for await (const manifestPath of find.findFiles("**/.projen/files.json", {
|
|
43
43
|
cwd: root,
|
|
44
44
|
ignoreOptions: { dot: false },
|
|
45
45
|
})) {
|
|
@@ -54,12 +54,14 @@ function nativeGeneratedFiles(root: string): string[] {
|
|
|
54
54
|
return [...files];
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export function listGeneratedFiles(root: string = resolveRepoRoot()): string[] {
|
|
57
|
+
export async function listGeneratedFiles(root: string = resolveRepoRoot()): Promise<string[]> {
|
|
58
58
|
const rel = (f: string): string => toPosix(relative(root, f));
|
|
59
|
-
const custom = [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const custom: string[] = [];
|
|
60
|
+
for await (const file of find.findFiles("**/*", { cwd: root })) {
|
|
61
|
+
const absolute = join(root, file);
|
|
62
|
+
if (isGenerated(absolute)) custom.push(absolute);
|
|
63
|
+
}
|
|
64
|
+
return [...new Set([...(await nativeGeneratedFiles(root)), ...custom])]
|
|
63
65
|
.filter(existsSync)
|
|
64
66
|
.filter(
|
|
65
67
|
(file) =>
|
|
@@ -79,12 +81,17 @@ export function listGeneratedFiles(root: string = resolveRepoRoot()): string[] {
|
|
|
79
81
|
* own - removing the top-level dir takes it along. Other vendor/build/VCS dirs are
|
|
80
82
|
* skipped for speed.
|
|
81
83
|
*/
|
|
82
|
-
export function listNodeModulesDirs(root: string = resolveRepoRoot()): string[] {
|
|
84
|
+
export async function listNodeModulesDirs(root: string = resolveRepoRoot()): Promise<string[]> {
|
|
83
85
|
if (!existsSync(root)) return [];
|
|
84
86
|
const rel = (f: string): string => toPosix(relative(root, f));
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
const directories: string[] = [];
|
|
88
|
+
for await (const match of find.findFiles("**/node_modules", {
|
|
89
|
+
cwd: root,
|
|
90
|
+
ignoreOptions: { dot: false },
|
|
91
|
+
})) {
|
|
92
|
+
directories.push(join(root, match));
|
|
93
|
+
}
|
|
94
|
+
return directories.sort((a, b) => rel(a).localeCompare(rel(b)));
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
/**
|
package/src/dev-watch.ts
CHANGED
|
@@ -8,8 +8,3 @@ export const DEV_WATCH_SCRIPT = "dev-watch.ts";
|
|
|
8
8
|
export const DEV_RESTART_DEBOUNCE_MS = 15_000;
|
|
9
9
|
/** Interactive key that requests an immediate restart. */
|
|
10
10
|
export const DEV_RESTART_KEY = "r";
|
|
11
|
-
/**
|
|
12
|
-
* Process environment that skips wrapping or running the file watcher.
|
|
13
|
-
* Parsed with `configUtils.boolean` (`1` / `true` / `yes` disable watch).
|
|
14
|
-
*/
|
|
15
|
-
export const SERVER_WATCH_DISABLED_ENV = "SERVER_WATCH_DISABLED";
|
package/src/packages.ts
CHANGED
|
@@ -174,7 +174,7 @@ function packageOfMember(projectRoot: string, member: string): DiscoveredPackage
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
|
-
* Package dirs under `rootAbs`, found with a single `find.
|
|
177
|
+
* Package dirs under `rootAbs`, found with a single `find.findFilesSync` scan from
|
|
178
178
|
* `@dbx-tools/path` for module files beneath any `src/`. A package is the
|
|
179
179
|
* folder that OWNS the `src/` - the segments before the FIRST `src/` - so a package's
|
|
180
180
|
* own subfolders never become nested packages (outermost wins). Barrels/tests/decls
|
|
@@ -184,7 +184,7 @@ function packageOfMember(projectRoot: string, member: string): DiscoveredPackage
|
|
|
184
184
|
*/
|
|
185
185
|
function collectPackageDirs(rootAbs: string): string[] {
|
|
186
186
|
const owners = new Set<string>();
|
|
187
|
-
for (const file of find.
|
|
187
|
+
for (const file of find.findFilesSync(SRC_MODULE_GLOB, { cwd: rootAbs })) {
|
|
188
188
|
if (!isModuleFile(file)) continue;
|
|
189
189
|
const segs = toPosix(file).split("/");
|
|
190
190
|
const srcIdx = segs.indexOf("src");
|
|
@@ -328,7 +328,7 @@ export function resolveAllPythonNodeBindings(
|
|
|
328
328
|
export function pythonNodeBindingProjects(projectRoot: string): string[] {
|
|
329
329
|
return [
|
|
330
330
|
...find
|
|
331
|
-
.
|
|
331
|
+
.findFilesSync("**/pyproject.toml", { cwd: projectRoot })
|
|
332
332
|
.filter((file) => {
|
|
333
333
|
const manifest = parse(readFileSync(resolve(projectRoot, file), "utf8")) as {
|
|
334
334
|
tool?: { dbx_tools?: { node_bindings?: unknown } };
|
package/src/shared-core-usage.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* unused exports and duplicated owned helpers.
|
|
7
7
|
*/
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
|
-
import { join, relative } from "node:path";
|
|
9
|
+
import { join, relative, resolve } from "node:path";
|
|
10
10
|
import { find } from "@dbx-tools/path";
|
|
11
11
|
import * as core from "@dbx-tools/shared-core";
|
|
12
12
|
import { PACKAGE_IDENTIFIER, object } from "@dbx-tools/shared-core";
|
|
@@ -59,7 +59,7 @@ function namespaceMap(coreDir: string): Readonly<Record<string, string>> {
|
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
function sourceFiles(root: string, includeGenerated: boolean): string[] {
|
|
62
|
+
async function sourceFiles(root: string, includeGenerated: boolean): Promise<string[]> {
|
|
63
63
|
const ignore = [
|
|
64
64
|
"**/node_modules/**",
|
|
65
65
|
"**/lib/**",
|
|
@@ -69,7 +69,11 @@ function sourceFiles(root: string, includeGenerated: boolean): string[] {
|
|
|
69
69
|
"**/_runtime.js",
|
|
70
70
|
];
|
|
71
71
|
if (!includeGenerated) ignore.push(`**/${PYTHON_GENERATED_PACKAGE}/**`);
|
|
72
|
-
|
|
72
|
+
const files: string[] = [];
|
|
73
|
+
for await (const file of find.findFiles(SOURCE_PATTERN, { cwd: root, ignore })) {
|
|
74
|
+
files.push(resolve(root, file));
|
|
75
|
+
}
|
|
76
|
+
return files.sort();
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
function classifyFile(
|
|
@@ -114,11 +118,13 @@ function mentionsExport(
|
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
/** Classify every namespace runtime export against repository callers. */
|
|
117
|
-
export function sharedCoreExportUsage(
|
|
121
|
+
export async function sharedCoreExportUsage(
|
|
122
|
+
root: string = repoRoot,
|
|
123
|
+
): Promise<SharedCoreExportUsage[]> {
|
|
118
124
|
const coreDir = sharedCorePackageDir(root);
|
|
119
125
|
const coreDirRel = relative(root, coreDir);
|
|
120
126
|
const namespaces = namespaceMap(coreDir);
|
|
121
|
-
const files = sourceFiles(root, true).map((file) => ({
|
|
127
|
+
const files = (await sourceFiles(root, true)).map((file) => ({
|
|
122
128
|
path: relative(root, file),
|
|
123
129
|
text: readFileSync(file, "utf8"),
|
|
124
130
|
}));
|
|
@@ -152,9 +158,9 @@ export function sharedCoreExportUsage(root: string = repoRoot): SharedCoreExport
|
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
/** Local copies of helpers owned by shared-core. */
|
|
155
|
-
export function duplicatedOwnedHelpers(root: string = repoRoot): string[] {
|
|
161
|
+
export async function duplicatedOwnedHelpers(root: string = repoRoot): Promise<string[]> {
|
|
156
162
|
const duplicates: string[] = [];
|
|
157
|
-
for (const file of sourceFiles(root, false)) {
|
|
163
|
+
for (const file of await sourceFiles(root, false)) {
|
|
158
164
|
const relativePath = relative(root, file);
|
|
159
165
|
if (OWNED_HELPER_FILES.has(relativePath)) continue;
|
|
160
166
|
if (relativePath.startsWith("packages/js/shared/core/test/")) continue;
|
package/src/watch.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { isAbsolute, resolve } from "node:path";
|
|
19
19
|
import { watch as pathWatch } from "@dbx-tools/path";
|
|
20
|
-
import { asyncUtils, log } from "@dbx-tools/shared-core";
|
|
20
|
+
import { asyncUtils, errorUtils, log } from "@dbx-tools/shared-core";
|
|
21
21
|
import { isGeneratedFile, recordedRoots, repoRoot } from "./packages.ts";
|
|
22
22
|
import { withWorkspaceMutationLock } from "./workspace-lock.ts";
|
|
23
23
|
|
|
@@ -90,12 +90,12 @@ export interface WatchLoopOptions {
|
|
|
90
90
|
check?: (changed: string[]) => boolean | Promise<boolean>;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
export function watchLoop(
|
|
93
|
+
export async function watchLoop(
|
|
94
94
|
tag: string,
|
|
95
95
|
paths: string[],
|
|
96
96
|
onBatch: (changed: string[]) => void | Promise<void>,
|
|
97
97
|
config: WatchLoopOptions = {},
|
|
98
|
-
): void {
|
|
98
|
+
): Promise<void> {
|
|
99
99
|
const { ignoreOptions, check } = config;
|
|
100
100
|
const pending = new Set<string>();
|
|
101
101
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
@@ -119,7 +119,7 @@ export function watchLoop(
|
|
|
119
119
|
});
|
|
120
120
|
}
|
|
121
121
|
} catch (err) {
|
|
122
|
-
logger.error(`${tag} cycle failed
|
|
122
|
+
logger.error(`${tag} cycle failed`, { error: errorUtils.toError(err) });
|
|
123
123
|
} finally {
|
|
124
124
|
running = false;
|
|
125
125
|
if (rerun) {
|
|
@@ -129,7 +129,7 @@ export function watchLoop(
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
const watcher = pathWatch.watchFiles(paths, {
|
|
132
|
+
const watcher = await pathWatch.watchFiles(paths, {
|
|
133
133
|
cwd: repoRoot,
|
|
134
134
|
ignoreInitial: true,
|
|
135
135
|
ignore: (path) => ignoredPath(path),
|
|
@@ -156,7 +156,7 @@ export function watchLoop(
|
|
|
156
156
|
timer = setTimeout(() => void flush(), DEBOUNCE_MS);
|
|
157
157
|
});
|
|
158
158
|
watcher.on("error", (err) => {
|
|
159
|
-
logger.error(`${tag} watcher error
|
|
159
|
+
logger.error(`${tag} watcher error`, { error: errorUtils.toError(err) });
|
|
160
160
|
const code = (err as NodeJS.ErrnoException | undefined)?.code;
|
|
161
161
|
if (code === undefined || !FATAL_WATCH_ERROR_CODES.has(code)) return;
|
|
162
162
|
logger.error(`${tag}: ${code} leaves the watcher blind - exiting so it is restarted`);
|
package/tasks/barrels.ts
CHANGED
|
@@ -57,7 +57,7 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
57
57
|
// Watch the package roots; a source edit inside a package rebuilds just that
|
|
58
58
|
// package's `index.ts` barrel (no re-synth - the projenrc watcher owns that).
|
|
59
59
|
// watchLoop already drops generated paths, so a barrel write never re-triggers us.
|
|
60
|
-
watchLoop(
|
|
60
|
+
await watchLoop(
|
|
61
61
|
"barrels",
|
|
62
62
|
watchRoots(),
|
|
63
63
|
(changed) => {
|
package/tasks/clean.ts
CHANGED
|
@@ -27,8 +27,7 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
27
27
|
args,
|
|
28
28
|
);
|
|
29
29
|
|
|
30
|
-
const files = listGeneratedFiles();
|
|
31
|
-
const nodeModules = listNodeModulesDirs();
|
|
30
|
+
const [files, nodeModules] = await Promise.all([listGeneratedFiles(), listNodeModulesDirs()]);
|
|
32
31
|
const targets = [...files, ...nodeModules];
|
|
33
32
|
|
|
34
33
|
if (targets.length === 0) {
|
|
@@ -4,7 +4,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
4
4
|
import { availableParallelism } from "node:os";
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
6
|
import * as exec from "@dbx-tools/core/exec";
|
|
7
|
-
import { log } from "@dbx-tools/shared-core";
|
|
7
|
+
import { errorUtils, log } from "@dbx-tools/shared-core";
|
|
8
8
|
import { runTaskMain } from "./cli.ts";
|
|
9
9
|
|
|
10
10
|
const logger = log.logger("projen:compile");
|
|
@@ -116,7 +116,9 @@ export async function main(): Promise<void> {
|
|
|
116
116
|
let failed = false;
|
|
117
117
|
for (const [index, result] of results.entries()) {
|
|
118
118
|
if (result.status === "rejected") {
|
|
119
|
-
logger.error(`${jobs[index]!.name} compile failed
|
|
119
|
+
logger.error(`${jobs[index]!.name} compile failed`, {
|
|
120
|
+
error: errorUtils.toError(result.reason),
|
|
121
|
+
});
|
|
120
122
|
failed = true;
|
|
121
123
|
} else if (result.value.exitCode !== 0) {
|
|
122
124
|
logger.error(`${jobs[index]!.name} compile exited with ${result.value.exitCode}`);
|
package/tasks/dev-watch.ts
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env -S bun
|
|
2
2
|
/** Restart a development command after relevant workspace changes settle. */
|
|
3
3
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
4
|
+
import { serializeArgs } from "@dbx-tools/cli-args";
|
|
4
5
|
import * as exec from "@dbx-tools/core/exec";
|
|
5
6
|
import { watch as pathWatch } from "@dbx-tools/path";
|
|
6
|
-
import { log } from "@dbx-tools/shared-core";
|
|
7
|
+
import { asyncUtils, errorUtils, log } from "@dbx-tools/shared-core";
|
|
7
8
|
import { CommanderError } from "commander";
|
|
8
9
|
import { z } from "zod";
|
|
9
10
|
import { parsedTaskOptions, runTaskMain, taskCommand, taskPositionals } from "./cli.ts";
|
|
10
|
-
import {
|
|
11
|
-
DEV_RESTART_DEBOUNCE_MS,
|
|
12
|
-
DEV_RESTART_KEY,
|
|
13
|
-
DEV_WATCH_TASK,
|
|
14
|
-
SERVER_WATCH_DISABLED_ENV,
|
|
15
|
-
} from "../src/dev-watch.ts";
|
|
11
|
+
import { DEV_RESTART_DEBOUNCE_MS, DEV_RESTART_KEY, DEV_WATCH_TASK } from "../src/dev-watch.ts";
|
|
16
12
|
import {
|
|
17
13
|
readPackageManifest,
|
|
18
14
|
recordedPackages,
|
|
@@ -23,33 +19,41 @@ import {
|
|
|
23
19
|
const logger = log.logger("projen:dev-watch");
|
|
24
20
|
const SHUTDOWN_TIMEOUT_MS = 2_000;
|
|
25
21
|
|
|
26
|
-
export interface DevWatchOptions {
|
|
27
|
-
readonly command: readonly string[];
|
|
28
|
-
readonly debounceMs: number;
|
|
29
|
-
readonly restartKey: string;
|
|
30
|
-
/** When true, run the command once and skip file-change restarts. */
|
|
31
|
-
readonly serverWatchDisabled: boolean;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
22
|
export const DevWatchOptionsSchema = z.object({
|
|
35
23
|
debounceMs: z.coerce
|
|
36
24
|
.number()
|
|
37
25
|
.int()
|
|
38
26
|
.nonnegative("Debounce must be a non-negative number of milliseconds")
|
|
39
27
|
.default(DEV_RESTART_DEBOUNCE_MS)
|
|
40
|
-
.describe("Quiet period before restarting the command")
|
|
28
|
+
.describe("Quiet period before restarting the command")
|
|
29
|
+
.meta({ short: false }),
|
|
41
30
|
restartKey: z
|
|
42
31
|
.string()
|
|
43
32
|
.refine((value) => Array.from(value).length === 1, "Restart key must be exactly one character")
|
|
44
33
|
.default(DEV_RESTART_KEY)
|
|
45
34
|
.describe("Interactive immediate-restart key"),
|
|
46
|
-
|
|
35
|
+
watchDisable: z
|
|
47
36
|
.boolean()
|
|
48
37
|
.default(false)
|
|
49
|
-
.describe("Run the command once without watching")
|
|
50
|
-
.meta({ env:
|
|
38
|
+
.describe("Run the command once without watching files or restarting on changes")
|
|
39
|
+
.meta({ env: "DEV_WATCH_DISABLE", short: "d" }),
|
|
40
|
+
watchInclude: z
|
|
41
|
+
.array(z.string())
|
|
42
|
+
.default([])
|
|
43
|
+
.describe("Glob patterns to watch; replaces the default workspace-package directories")
|
|
44
|
+
.meta({ env: "DEV_WATCH_INCLUDE", short: "i" }),
|
|
45
|
+
watchExclude: z
|
|
46
|
+
.array(z.string())
|
|
47
|
+
.default([])
|
|
48
|
+
.describe("Glob patterns to ignore after the include set is chosen")
|
|
49
|
+
.meta({ env: "DEV_WATCH_EXCLUDE", short: "e" }),
|
|
51
50
|
});
|
|
52
51
|
|
|
52
|
+
/** Parsed watcher flags plus the pass-through command argv. */
|
|
53
|
+
export type DevWatchOptions = z.output<typeof DevWatchOptionsSchema> & {
|
|
54
|
+
readonly command: readonly string[];
|
|
55
|
+
};
|
|
56
|
+
|
|
53
57
|
interface WorkspacePackage {
|
|
54
58
|
readonly dir: string;
|
|
55
59
|
readonly name?: string;
|
|
@@ -76,15 +80,50 @@ export function parseDevWatchOptions(args: readonly string[]): DevWatchOptions {
|
|
|
76
80
|
.parse([...args], { from: "user" });
|
|
77
81
|
const options = parsedTaskOptions(program, DevWatchOptionsSchema);
|
|
78
82
|
const [command, commandArgs = []] = taskPositionals(program) as [string, string[]?];
|
|
79
|
-
if (options.serverWatchDisabled) process.env[SERVER_WATCH_DISABLED_ENV] = "1";
|
|
80
83
|
return {
|
|
84
|
+
...options,
|
|
81
85
|
command: [command, ...commandArgs],
|
|
82
|
-
debounceMs: options.debounceMs,
|
|
83
|
-
restartKey: options.restartKey,
|
|
84
|
-
serverWatchDisabled: options.serverWatchDisabled,
|
|
85
86
|
};
|
|
86
87
|
}
|
|
87
88
|
|
|
89
|
+
/** Watcher flags the root demo may forward into a nested `dev:watch`. */
|
|
90
|
+
export type DevWatchForwardOptions = Pick<
|
|
91
|
+
DevWatchOptions,
|
|
92
|
+
"watchDisable" | "watchInclude" | "watchExclude"
|
|
93
|
+
>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parse `--watch-disable` / `--watch-include` / `--watch-exclude` from argv that
|
|
97
|
+
* may contain unrelated tokens (the root demo forwards only these flags).
|
|
98
|
+
*/
|
|
99
|
+
export function parseWatchGlobOptions(args: readonly string[]): DevWatchForwardOptions {
|
|
100
|
+
const program = taskCommand(
|
|
101
|
+
import.meta.url,
|
|
102
|
+
"Restart a development command after watched changes settle",
|
|
103
|
+
DevWatchOptionsSchema,
|
|
104
|
+
)
|
|
105
|
+
.name(DEV_WATCH_TASK)
|
|
106
|
+
.exitOverride()
|
|
107
|
+
.allowUnknownOption(true)
|
|
108
|
+
.allowExcessArguments(true)
|
|
109
|
+
.parse([...args], { from: "user" });
|
|
110
|
+
const options = parsedTaskOptions(program, DevWatchOptionsSchema);
|
|
111
|
+
return {
|
|
112
|
+
watchDisable: options.watchDisable,
|
|
113
|
+
watchInclude: options.watchInclude,
|
|
114
|
+
watchExclude: options.watchExclude,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Serialize forwarded watcher flags for a nested `dev:watch`. */
|
|
119
|
+
export function serializedWatchGlobArgs(options: DevWatchForwardOptions): string[] {
|
|
120
|
+
return serializeArgs({
|
|
121
|
+
...(options.watchDisable ? { watchDisable: true } : {}),
|
|
122
|
+
watchInclude: options.watchInclude,
|
|
123
|
+
watchExclude: options.watchExclude,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
88
127
|
function containsPath(parent: string, candidate: string): boolean {
|
|
89
128
|
const rel = relative(parent, candidate);
|
|
90
129
|
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
@@ -156,6 +195,23 @@ export function devWatchDirectories(
|
|
|
156
195
|
return dependencies.length > 0 ? dependencies : [owner.dir];
|
|
157
196
|
}
|
|
158
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Choose watch paths for {@link pathWatch.watchFiles}.
|
|
200
|
+
* Default workspace-package directories apply until `--watch-include` is set;
|
|
201
|
+
* `--watch-exclude` is always passed through as ignore globs.
|
|
202
|
+
*/
|
|
203
|
+
export function devWatchTargets(
|
|
204
|
+
command: readonly string[],
|
|
205
|
+
cwd: string,
|
|
206
|
+
include: readonly string[] = [],
|
|
207
|
+
exclude: readonly string[] = [],
|
|
208
|
+
): { paths: readonly string[]; ignore: readonly string[] } {
|
|
209
|
+
return {
|
|
210
|
+
paths: include.length > 0 ? [...include] : devWatchDirectories(command, cwd),
|
|
211
|
+
ignore: [...exclude],
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
159
215
|
/** Compare one raw terminal character with the configured restart key. */
|
|
160
216
|
export function isRestartKey(key: string, restartKey: string): boolean {
|
|
161
217
|
return key === restartKey || key.toLocaleLowerCase() === restartKey.toLocaleLowerCase();
|
|
@@ -172,12 +228,13 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
172
228
|
return;
|
|
173
229
|
}
|
|
174
230
|
const cwd = process.cwd();
|
|
175
|
-
|
|
176
|
-
|
|
231
|
+
const commandLabel = options.command.map((part) => JSON.stringify(part)).join(" ");
|
|
232
|
+
if (options.watchDisable) {
|
|
233
|
+
logger.info(`watch disabled; running ${commandLabel}`);
|
|
177
234
|
const [command, ...commandArgs] = options.command;
|
|
178
235
|
const { exitCode } = await exec.spawn(command!, commandArgs, {
|
|
179
236
|
cwd,
|
|
180
|
-
stdin: "
|
|
237
|
+
stdin: "inherit",
|
|
181
238
|
stdout: "inherit",
|
|
182
239
|
stderr: "inherit",
|
|
183
240
|
check: false,
|
|
@@ -187,19 +244,37 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
187
244
|
}
|
|
188
245
|
|
|
189
246
|
const root = resolveRepoRoot(cwd);
|
|
190
|
-
const
|
|
191
|
-
|
|
247
|
+
const { paths: watchPaths, ignore: watchIgnore } = devWatchTargets(
|
|
248
|
+
options.command,
|
|
249
|
+
cwd,
|
|
250
|
+
options.watchInclude,
|
|
251
|
+
options.watchExclude,
|
|
252
|
+
);
|
|
192
253
|
let child: exec.ChildProcessResult | undefined;
|
|
193
254
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
194
255
|
let restartReason: string | undefined;
|
|
195
256
|
let restarting = false;
|
|
196
257
|
let stopping = false;
|
|
197
258
|
|
|
198
|
-
const watcher = pathWatch.watchFiles(
|
|
259
|
+
const watcher = await pathWatch.watchFiles([...watchPaths], {
|
|
199
260
|
cwd: root,
|
|
261
|
+
ignore: watchIgnore.length > 0 ? [...watchIgnore] : undefined,
|
|
200
262
|
ignoreInitial: true,
|
|
263
|
+
ignoreOptions: {
|
|
264
|
+
git: true,
|
|
265
|
+
},
|
|
201
266
|
});
|
|
202
267
|
|
|
268
|
+
function interruptChild(): void {
|
|
269
|
+
const current = child;
|
|
270
|
+
if (!current?.pid) return;
|
|
271
|
+
try {
|
|
272
|
+
current.kill("SIGINT");
|
|
273
|
+
} catch {
|
|
274
|
+
// The command already exited.
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
203
278
|
async function stopChild(): Promise<void> {
|
|
204
279
|
const current = child;
|
|
205
280
|
if (!current) return;
|
|
@@ -210,7 +285,9 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
210
285
|
forceTimeoutMs: SHUTDOWN_TIMEOUT_MS,
|
|
211
286
|
});
|
|
212
287
|
} catch (err) {
|
|
213
|
-
logger.error("failed to stop command process tree
|
|
288
|
+
logger.error("failed to stop command process tree", {
|
|
289
|
+
error: errorUtils.toError(err),
|
|
290
|
+
});
|
|
214
291
|
}
|
|
215
292
|
}
|
|
216
293
|
|
|
@@ -236,7 +313,7 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
236
313
|
.catch((err) => {
|
|
237
314
|
if (child !== current || stopping) return;
|
|
238
315
|
child = undefined;
|
|
239
|
-
logger.error("command failed
|
|
316
|
+
logger.error("command failed", { error: errorUtils.toError(err) });
|
|
240
317
|
});
|
|
241
318
|
}
|
|
242
319
|
|
|
@@ -269,11 +346,12 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
269
346
|
}
|
|
270
347
|
|
|
271
348
|
watcher.on("all", scheduleRestart);
|
|
272
|
-
watcher.on("error", (err) => logger.error("watcher error
|
|
349
|
+
watcher.on("error", (err) => logger.error("watcher error", { error: errorUtils.toError(err) }));
|
|
273
350
|
watcher.on("ready", () => {
|
|
274
|
-
const
|
|
351
|
+
const count = watchPaths.length;
|
|
352
|
+
const source = options.watchInclude.length > 0 ? "include glob" : "workspace directory";
|
|
275
353
|
logger.info(
|
|
276
|
-
`watching ${
|
|
354
|
+
`watching ${count} ${source}${count === 1 ? "" : "s"} with ${options.debounceMs}ms restart debounce`,
|
|
277
355
|
);
|
|
278
356
|
logger.info(`press ${JSON.stringify(options.restartKey)} to restart; Ctrl-C to stop`);
|
|
279
357
|
});
|
|
@@ -292,33 +370,37 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
292
370
|
}
|
|
293
371
|
}
|
|
294
372
|
};
|
|
373
|
+
|
|
374
|
+
function restoreStdin(): void {
|
|
375
|
+
stdin.off("data", onInput);
|
|
376
|
+
if (stdin.isTTY) stdin.setRawMode(wasRaw);
|
|
377
|
+
stdin.pause();
|
|
378
|
+
}
|
|
379
|
+
|
|
295
380
|
if (stdin.isTTY) stdin.setRawMode(true);
|
|
296
381
|
stdin.resume();
|
|
297
382
|
stdin.on("data", onInput);
|
|
298
383
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
finish = resolveComplete;
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
async function shutdown(): Promise<void> {
|
|
305
|
-
if (stopping) return;
|
|
384
|
+
async function shutdown(exitCode = 0): Promise<void> {
|
|
385
|
+
if (stopping) process.exit(exitCode || 130);
|
|
306
386
|
stopping = true;
|
|
307
387
|
clearTimeout(timer);
|
|
308
388
|
restartReason = undefined;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
389
|
+
restoreStdin();
|
|
390
|
+
interruptChild();
|
|
391
|
+
await Promise.race([
|
|
392
|
+
Promise.allSettled([watcher.close(), stopChild()]),
|
|
393
|
+
asyncUtils.sleep(SHUTDOWN_TIMEOUT_MS),
|
|
394
|
+
]);
|
|
395
|
+
process.exit(exitCode);
|
|
314
396
|
}
|
|
315
397
|
|
|
316
398
|
for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"] as const) {
|
|
317
|
-
process.
|
|
399
|
+
process.on(signal, () => void shutdown());
|
|
318
400
|
}
|
|
319
401
|
|
|
320
402
|
requestRestart("initial start");
|
|
321
|
-
await
|
|
403
|
+
await new Promise<void>(() => {});
|
|
322
404
|
}
|
|
323
405
|
|
|
324
406
|
await runTaskMain(import.meta, main);
|
package/tasks/projenrc.ts
CHANGED
|
@@ -26,8 +26,8 @@ function resynthWatchPaths(): string[] {
|
|
|
26
26
|
// makes the watch intelligent vs stock `projen --watch`, which re-synths on any tree
|
|
27
27
|
// change. `{ dot: false }` keeps the default dotfile ignore group from pruning dotfile
|
|
28
28
|
// targets. (A one-shot "projenrc" is just a synth, i.e. `bun run default`.)
|
|
29
|
-
export function main(): void {
|
|
30
|
-
watchLoop(
|
|
29
|
+
export async function main(): Promise<void> {
|
|
30
|
+
await watchLoop(
|
|
31
31
|
"projenrc",
|
|
32
32
|
resynthWatchPaths(),
|
|
33
33
|
() => {
|
|
@@ -63,7 +63,7 @@ export async function main(): Promise<void> {
|
|
|
63
63
|
await withWorkspaceMutationLock(repoRoot, () => generatePythonNodeBindings(repoRoot));
|
|
64
64
|
logger.success("generated all Python Node bindings");
|
|
65
65
|
|
|
66
|
-
watchLoop(
|
|
66
|
+
await watchLoop(
|
|
67
67
|
"python-node-bindings",
|
|
68
68
|
watchPaths(configs),
|
|
69
69
|
(changed) => {
|
|
@@ -690,7 +690,8 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
690
690
|
path: string,
|
|
691
691
|
preferredName?: string,
|
|
692
692
|
): PythonRecord | undefined {
|
|
693
|
-
|
|
693
|
+
// Named intersections (`Omit<...> & { nested?: Named }`) are records.
|
|
694
|
+
if (!(type.flags & ts.TypeFlags.Object) && !type.isIntersection()) return undefined;
|
|
694
695
|
if (checker.isArrayType(type) || type.getCallSignatures().length > 0) return undefined;
|
|
695
696
|
if (checker.getIndexTypeOfType(type, ts.IndexKind.String)) return undefined;
|
|
696
697
|
const symbolName = type.aliasSymbol?.getName() ?? type.getSymbol()?.getName();
|
|
@@ -32,7 +32,7 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
32
32
|
await withWorkspaceMutationLock(repoRoot, build);
|
|
33
33
|
logger.success("built shared Python Node runtime");
|
|
34
34
|
|
|
35
|
-
watchLoop("python-node-runtime", [buildScript, shimDirectory], () => {
|
|
35
|
+
await watchLoop("python-node-runtime", [buildScript, shimDirectory], () => {
|
|
36
36
|
build();
|
|
37
37
|
logger.success("rebuilt shared Python Node runtime");
|
|
38
38
|
});
|
package/tasks/release.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import * as projectUtils from "@dbx-tools/core/project-utils";
|
|
6
|
-
import { log } from "@dbx-tools/shared-core";
|
|
6
|
+
import { errorUtils, log } from "@dbx-tools/shared-core";
|
|
7
7
|
import type { Command } from "commander";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { parsedTaskOptions, runTaskMain, taskCommand } from "./cli.ts";
|
|
@@ -149,7 +149,7 @@ function pushAnnotatedReleaseTag(options: {
|
|
|
149
149
|
} catch (error) {
|
|
150
150
|
if (remoteRefCreated) throw error;
|
|
151
151
|
logger.warn("GitHub API tag creation failed; using git push", {
|
|
152
|
-
error,
|
|
152
|
+
error: errorUtils.toError(error),
|
|
153
153
|
repository: githubAccount.remote.repository,
|
|
154
154
|
});
|
|
155
155
|
runTaskCommand(root, "git", ["push", remote, `refs/tags/${tag}`]);
|
|
@@ -233,7 +233,7 @@ export async function runRelease(
|
|
|
233
233
|
readonly validationTasks?: readonly string[];
|
|
234
234
|
/** After tagging, stage and deploy the AppKit demo app. Off by default. */
|
|
235
235
|
readonly demoDeploy?: boolean;
|
|
236
|
-
/**
|
|
236
|
+
/** Databricks CLI profile used only by the optional local demo deployment. */
|
|
237
237
|
readonly demoProfile?: string;
|
|
238
238
|
/** Write `docs/releases/vX.Y.Z.md` via Genie, with a git-log fallback. On by default. */
|
|
239
239
|
readonly releaseNotes?: boolean;
|
|
@@ -249,11 +249,7 @@ export async function runRelease(
|
|
|
249
249
|
const { branch, prefix, remote, root } = options;
|
|
250
250
|
const selection = releaseStepSelection(options);
|
|
251
251
|
const install = options.install ?? "auto";
|
|
252
|
-
const demoProfile = options.demoProfile?.trim();
|
|
253
252
|
|
|
254
|
-
if (options.demoDeploy && !demoProfile) {
|
|
255
|
-
throw new Error("--demo-deploy requires --profile <name>");
|
|
256
|
-
}
|
|
257
253
|
if (options.releaseNotesText !== undefined && options.releaseNotesFile !== undefined) {
|
|
258
254
|
throw new Error("--release-notes-text and --release-notes-file are mutually exclusive");
|
|
259
255
|
}
|
|
@@ -364,8 +360,13 @@ export async function runRelease(
|
|
|
364
360
|
});
|
|
365
361
|
}
|
|
366
362
|
|
|
367
|
-
if (options.demoDeploy
|
|
368
|
-
runTaskCommand(root, "bun", ["run", "demo:deploy",
|
|
363
|
+
if (options.demoDeploy) {
|
|
364
|
+
runTaskCommand(root, "bun", ["run", "demo:deploy"], {
|
|
365
|
+
env: {
|
|
366
|
+
...process.env,
|
|
367
|
+
...(options.demoProfile ? { DATABRICKS_CONFIG_PROFILE: options.demoProfile } : {}),
|
|
368
|
+
},
|
|
369
|
+
});
|
|
369
370
|
}
|
|
370
371
|
|
|
371
372
|
return tag;
|
|
@@ -420,8 +421,7 @@ export const ReleaseOptionsSchema = z.object({
|
|
|
420
421
|
.trim()
|
|
421
422
|
.min(1)
|
|
422
423
|
.optional()
|
|
423
|
-
.describe("
|
|
424
|
-
.meta({ env: [], helpDefault: false }),
|
|
424
|
+
.describe("Databricks CLI profile for the optional demo deployment"),
|
|
425
425
|
localPublish: z.boolean().default(true).describe("Publish to configured local registries"),
|
|
426
426
|
localRegistry: z
|
|
427
427
|
.string()
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
import { runTaskMain } from "./cli.ts";
|
|
4
4
|
import { formatSharedCoreUsage, sharedCoreExportUsage } from "../src/shared-core-usage.ts";
|
|
5
5
|
|
|
6
|
-
export function main(): void {
|
|
7
|
-
process.stdout.write(formatSharedCoreUsage(sharedCoreExportUsage()));
|
|
6
|
+
export async function main(): Promise<void> {
|
|
7
|
+
process.stdout.write(formatSharedCoreUsage(await sharedCoreExportUsage()));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
await runTaskMain(import.meta, main);
|
package/tasks/sync.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env -S bun
|
|
2
2
|
/** Synthesize once or supervise Projen, barrels, and registered focused watchers. */
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { log } from "@dbx-tools/shared-core";
|
|
4
|
+
import { errorUtils, log } from "@dbx-tools/shared-core";
|
|
5
5
|
import concurrently from "concurrently";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { runTaskMain, taskCommand, taskOptions } from "./cli.ts";
|
|
@@ -84,10 +84,7 @@ export async function main(args: string[] = process.argv.slice(2)): Promise<void
|
|
|
84
84
|
} catch (err) {
|
|
85
85
|
// A tree that doesn't synth is precisely when the watcher is most useful: the edit
|
|
86
86
|
// that repairs it is the one the projenrc watcher is sitting there waiting for.
|
|
87
|
-
logger.error(
|
|
88
|
-
"initial sync failed - watching anyway:",
|
|
89
|
-
err instanceof Error ? err.message : err,
|
|
90
|
-
);
|
|
87
|
+
logger.error("initial sync failed - watching anyway", { error: errorUtils.toError(err) });
|
|
91
88
|
}
|
|
92
89
|
|
|
93
90
|
const watchers = [
|
package/tasks/version-check.ts
CHANGED
|
@@ -24,7 +24,7 @@ function pythonVersion(path: string): string | undefined {
|
|
|
24
24
|
return typeof manifest.project?.version === "string" ? manifest.project.version : undefined;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export function main(): void {
|
|
27
|
+
export async function main(): Promise<void> {
|
|
28
28
|
const root = projectUtils.root() ?? process.cwd();
|
|
29
29
|
const version = readWorkspaceVersion(root);
|
|
30
30
|
const mismatches: string[] = [];
|
|
@@ -37,7 +37,7 @@ export function main(): void {
|
|
|
37
37
|
check(`${pkg.path}/package.json`, manifestVersion(join(pkg.dir, "package.json")));
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
for (const path of find.findFiles("**/pyproject.toml", { cwd: root })) {
|
|
40
|
+
for await (const path of find.findFiles("**/pyproject.toml", { cwd: root })) {
|
|
41
41
|
check(path, pythonVersion(join(root, path)));
|
|
42
42
|
}
|
|
43
43
|
if (mismatches.length > 0) {
|