@dbx-tools/projen 0.6.39 → 0.6.41
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/index.ts +2 -2
- package/package.json +25 -23
- package/src/bun-app.ts +164 -0
- package/src/packages.ts +6 -4
- package/src/pnpm-workspace.ts +73 -12
- package/src/project.ts +94 -48
- package/src/release.ts +114 -38
- package/src/tags.ts +28 -14
- package/tasks/bump.ts +41 -87
- package/tasks/publish.ts +156 -0
- package/src/vite.ts +0 -99
package/src/project.ts
CHANGED
|
@@ -22,7 +22,13 @@ import { applyCompiledPublish } from "./publish.ts";
|
|
|
22
22
|
import { DBXToolsRelease, type StandaloneRelease } from "./release.ts";
|
|
23
23
|
import { AGNOSTIC_COMPILER_OPTIONS, PACKAGE_TAG_MIXINS, type PackageTag } from "./tags.ts";
|
|
24
24
|
import { DBXToolsRootTsconfig } from "./tsconfig.ts";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
BUN_APP_OVERRIDES,
|
|
27
|
+
BunBuildFile,
|
|
28
|
+
BunDevServerFile,
|
|
29
|
+
BunfigFile,
|
|
30
|
+
RootBunfigFile,
|
|
31
|
+
} from "./bun-app.ts";
|
|
26
32
|
import { DBXToolsVsCode } from "./vscode.ts";
|
|
27
33
|
import {
|
|
28
34
|
DEFAULT_PACKAGE_ROOTS,
|
|
@@ -147,11 +153,11 @@ function applyRepository(project: javascript.NodeProject, override?: string): vo
|
|
|
147
153
|
});
|
|
148
154
|
}
|
|
149
155
|
|
|
150
|
-
/** Inherit a parent's package manager, else
|
|
156
|
+
/** Inherit a parent's package manager, else bun. */
|
|
151
157
|
function inheritedPackageManager(
|
|
152
158
|
parent: javascript.NodeProject | undefined,
|
|
153
159
|
): javascript.NodePackageManager {
|
|
154
|
-
return parent?.package.packageManager ?? javascript.NodePackageManager.
|
|
160
|
+
return parent?.package.packageManager ?? javascript.NodePackageManager.BUN;
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
/** Override a package's generated tsconfig `compilerOptions` (later-wins per key). */
|
|
@@ -328,12 +334,19 @@ export const PROJEN_VERSION = "^0.101.16";
|
|
|
328
334
|
function defaultProjectOptions(options: DBXToolsProjectOptions): DBXToolsProjectOptions {
|
|
329
335
|
const isRoot = options.parent === undefined;
|
|
330
336
|
return {
|
|
331
|
-
|
|
337
|
+
// Bun owns install/run/build/test locally and in CI. projen renders
|
|
338
|
+
// `bun install`/`bunx` and a native `trustedDependencies` field from this.
|
|
339
|
+
// The engine still emits `pnpm-workspace.yaml` itself (see
|
|
340
|
+
// {@link PnpmWorkspaceState}) for the Databricks Apps platform, whose build
|
|
341
|
+
// phase installs with pnpm - so a deployed app keeps its catalog + build
|
|
342
|
+
// allowances even though the local/CI manager is bun.
|
|
343
|
+
packageManager: javascript.NodePackageManager.BUN,
|
|
332
344
|
// Pinned rather than left to projen's "latest": 0.101.16 is the first release
|
|
333
|
-
// whose `NodePackage`
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
//
|
|
345
|
+
// whose `NodePackage` renders bun's `trustedDependencies` natively. Under bun,
|
|
346
|
+
// projen does NOT create the `pnpm-workspace.yaml` component itself (that call
|
|
347
|
+
// site is gated to pnpm), so the engine constructs it directly ({@link
|
|
348
|
+
// PnpmWorkspaceState}). Floating would let an install cross that boundary
|
|
349
|
+
// silently, so the co-tested version is stated here and bumped deliberately.
|
|
337
350
|
projenVersion: PROJEN_VERSION,
|
|
338
351
|
defaultReleaseBranch: "main",
|
|
339
352
|
projenrcJs: false,
|
|
@@ -403,8 +416,8 @@ function copiedGitIgnoreOptions(
|
|
|
403
416
|
/**
|
|
404
417
|
* The engine's `TypeScriptProject` defaults - a superset of {@link defaultProjectOptions}.
|
|
405
418
|
* A DBXTools TS project can itself be the ROOT (a standalone compiling root), so the
|
|
406
|
-
* same parent-based root/child logic applies; this just layers on
|
|
407
|
-
* disables sample code.
|
|
419
|
+
* same parent-based root/child logic applies; this just layers on typescript +
|
|
420
|
+
* bun types and disables sample code. No `tsx`: bun runs `.ts` directly.
|
|
408
421
|
*/
|
|
409
422
|
function defaultTypeScriptProjectOptions(
|
|
410
423
|
options: DBXToolsTypeScriptProjectOptions,
|
|
@@ -417,15 +430,16 @@ function defaultTypeScriptProjectOptions(
|
|
|
417
430
|
// ESLint is configured once on the ROOT (see initProject) and lints the whole
|
|
418
431
|
// tree, so packages don't emit their own config. A caller can still override.
|
|
419
432
|
eslint: false,
|
|
420
|
-
devDeps: [...(base.devDeps ?? []), "
|
|
433
|
+
devDeps: [...(base.devDeps ?? []), "typescript@^5.9.3", "@types/bun@^1.3.14"],
|
|
421
434
|
...options,
|
|
422
435
|
...copiedGitIgnoreOptions(options),
|
|
423
436
|
};
|
|
424
437
|
}
|
|
425
438
|
|
|
426
|
-
// Pinned to match the subproject defaults so
|
|
439
|
+
// Pinned to match the subproject defaults so bun resolves a single typescript
|
|
427
440
|
// across the workspace (a bare name -> `*` could pull a second, newer major).
|
|
428
|
-
|
|
441
|
+
// `@types/bun` gives the `Bun.*` globals the server/app tags now use.
|
|
442
|
+
const DEV_DEPS_ROOT: string[] = ["typescript@^5.9.3", "@types/bun@^1.3.14"];
|
|
429
443
|
|
|
430
444
|
/** Options for {@link DBXToolsNodeProject} (the monorepo root). */
|
|
431
445
|
export interface DBXToolsProjectOptions
|
|
@@ -478,13 +492,22 @@ export interface DBXToolsProjectOptions
|
|
|
478
492
|
* `@dbx-tools/projen` engine in `projen/`, tagged `projen-v*`).
|
|
479
493
|
*/
|
|
480
494
|
readonly standaloneReleases?: readonly StandaloneRelease[];
|
|
495
|
+
/**
|
|
496
|
+
* Extra workspace member paths (repo-relative, POSIX) to list in the workspace
|
|
497
|
+
* config ALONGSIDE the discovered `packageRoots` members - for a package that
|
|
498
|
+
* is synthesized by its OWN `.projenrc.ts` (so it isn't a root subproject) but
|
|
499
|
+
* should still resolve as a workspace sibling. The `@dbx-tools/projen` engine in
|
|
500
|
+
* `projen/` is the case: it synthesizes itself (avoiding a dogfooding cycle) yet
|
|
501
|
+
* is a member of the single bun workspace, so the root links it from source.
|
|
502
|
+
*/
|
|
503
|
+
readonly extraWorkspaceMembers?: readonly string[];
|
|
481
504
|
}
|
|
482
505
|
|
|
483
506
|
/** Options for {@link DBXToolsTypeScriptProject} (a package, or a compiling root). */
|
|
484
507
|
export interface DBXToolsTypeScriptProjectOptions
|
|
485
508
|
extends Partial<typescript.TypeScriptProjectOptions>, DBXToolsProjectOptions {
|
|
486
|
-
/** Emit
|
|
487
|
-
readonly
|
|
509
|
+
/** Emit the projen-owned bun app scaffolding (`bunfig.toml`/`dev.ts`/`build.ts`). */
|
|
510
|
+
readonly bunApp?: boolean;
|
|
488
511
|
}
|
|
489
512
|
|
|
490
513
|
/**
|
|
@@ -498,6 +521,7 @@ export class DBXToolsNodeProject extends javascript.NodeProject implements DBXTo
|
|
|
498
521
|
pnpmWorkspace?: PnpmWorkspaceState;
|
|
499
522
|
rootTsconfig?: DBXToolsRootTsconfig;
|
|
500
523
|
vsCode?: DBXToolsVsCode;
|
|
524
|
+
private readonly extraWorkspaceMembers: readonly string[];
|
|
501
525
|
|
|
502
526
|
constructor(options: DBXToolsProjectOptions = {}) {
|
|
503
527
|
const { name, scope } = resolveIdentity(options);
|
|
@@ -505,11 +529,12 @@ export class DBXToolsNodeProject extends javascript.NodeProject implements DBXTo
|
|
|
505
529
|
options.release && options.releaseTrigger === undefined
|
|
506
530
|
? { releaseTrigger: ReleaseTrigger.tagged({ tags: ["v*"] }) }
|
|
507
531
|
: {};
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
//
|
|
511
|
-
//
|
|
512
|
-
// `
|
|
532
|
+
// Holds the workspace state (members/catalog/allowBuilds/overrides). Under
|
|
533
|
+
// bun, projen's base constructor does NOT create the `PnpmWorkspaceYaml`
|
|
534
|
+
// component (its `configurePnpm` call site is gated to pnpm), so this state's
|
|
535
|
+
// options are wired into a directly-constructed component below - AND mirrored
|
|
536
|
+
// into `package.json` (`workspaces`/`catalog`) for bun to read. The
|
|
537
|
+
// `pnpm-workspace.yaml` is still emitted for the Databricks Apps pnpm install.
|
|
513
538
|
const pnpmWorkspace = new PnpmWorkspaceState(options);
|
|
514
539
|
super({
|
|
515
540
|
...defaultProjectOptions(options),
|
|
@@ -522,7 +547,12 @@ export class DBXToolsNodeProject extends javascript.NodeProject implements DBXTo
|
|
|
522
547
|
});
|
|
523
548
|
|
|
524
549
|
this.pnpmWorkspace = pnpmWorkspace;
|
|
550
|
+
// Emit `pnpm-workspace.yaml` ourselves: under bun projen skips the native
|
|
551
|
+
// component, but the file is still required by the Databricks Apps platform
|
|
552
|
+
// (its build phase installs with pnpm and reads catalog + `allowBuilds`).
|
|
553
|
+
pnpmWorkspace.attachWorkspaceFile(this);
|
|
525
554
|
this.scope = scope;
|
|
555
|
+
this.extraWorkspaceMembers = options.extraWorkspaceMembers ?? [];
|
|
526
556
|
this.dbxToolsConfig = new DBXToolsConfig(this, options);
|
|
527
557
|
initProject(this, options);
|
|
528
558
|
}
|
|
@@ -531,7 +561,8 @@ export class DBXToolsNodeProject extends javascript.NodeProject implements DBXTo
|
|
|
531
561
|
super.preSynthesize();
|
|
532
562
|
// Members come from the attached subprojects, which the root's scan appends
|
|
533
563
|
// after construction - so the list is filled here, not in the constructor.
|
|
534
|
-
|
|
564
|
+
// `extraWorkspaceMembers` adds self-synthesizing siblings (e.g. `projen/`).
|
|
565
|
+
this.pnpmWorkspace?.resolveMembers(this, this.extraWorkspaceMembers);
|
|
535
566
|
preSynthesizeProject(this);
|
|
536
567
|
}
|
|
537
568
|
}
|
|
@@ -588,8 +619,19 @@ export class DBXToolsTypeScriptProject
|
|
|
588
619
|
"./package.json": "./package.json",
|
|
589
620
|
});
|
|
590
621
|
addPackageFiles(this, "index.ts", "src");
|
|
591
|
-
|
|
592
|
-
|
|
622
|
+
// `bun test` intercepts `node:test` (the suites keep using node:test) and
|
|
623
|
+
// runs it with bun's own fast runner. Args are FILTERS, not globs; a bare
|
|
624
|
+
// directory auto-discovers `*.test.ts` recursively. But `bun test` EXITS 1
|
|
625
|
+
// when it matches no files (unlike the old `tsx --test 'glob'`, which was a
|
|
626
|
+
// no-op), so guard it: only invoke when a `*.test.ts` exists, else succeed.
|
|
627
|
+
this.testTask.exec(
|
|
628
|
+
'find test -name "*.test.ts" 2>/dev/null | grep -q . && bun test test || true',
|
|
629
|
+
);
|
|
630
|
+
if (options.bunApp ?? false) {
|
|
631
|
+
new BunfigFile(this);
|
|
632
|
+
new BunDevServerFile(this);
|
|
633
|
+
new BunBuildFile(this);
|
|
634
|
+
}
|
|
593
635
|
initProject(this, options);
|
|
594
636
|
}
|
|
595
637
|
|
|
@@ -746,15 +788,17 @@ function registerRootTasks(project: javascript.NodeProject): void {
|
|
|
746
788
|
}
|
|
747
789
|
|
|
748
790
|
/**
|
|
749
|
-
* `
|
|
750
|
-
*
|
|
751
|
-
*
|
|
752
|
-
*
|
|
791
|
+
* `bun node_modules/@dbx-tools/projen/tasks/<script>` command for a projen task.
|
|
792
|
+
*
|
|
793
|
+
* Use the stable package symlink, never `require.resolve()`'s physical store
|
|
794
|
+
* path. A later install can change the peer-hash directory while leaving the
|
|
795
|
+
* package symlink valid; persisting the physical path made every generated task
|
|
796
|
+
* fail with ERR_MODULE_NOT_FOUND after such an update. bun runs the `.ts`
|
|
797
|
+
* directly (no tsx, no build step).
|
|
753
798
|
*/
|
|
754
|
-
export function taskScript(
|
|
755
|
-
const scriptPath = join(
|
|
756
|
-
|
|
757
|
-
return args ? `tsx ${rel} ${args}` : `tsx ${rel}`;
|
|
799
|
+
export function taskScript(_project: javascript.NodeProject, script: string, args = ""): string {
|
|
800
|
+
const scriptPath = toPosix(join("node_modules", "@dbx-tools", "projen", "tasks", script));
|
|
801
|
+
return args ? `bun ${scriptPath} ${args}` : `bun ${scriptPath}`;
|
|
758
802
|
}
|
|
759
803
|
|
|
760
804
|
/**
|
|
@@ -787,20 +831,21 @@ function initProject(
|
|
|
787
831
|
project.package.file.readonly = false;
|
|
788
832
|
|
|
789
833
|
// NodeProject has no built-in TS projenrc support (unlike TypeScriptProject), so
|
|
790
|
-
// wire `.projenrc.ts` through
|
|
791
|
-
//
|
|
834
|
+
// wire `.projenrc.ts` through a runner - this also populates the `default` task
|
|
835
|
+
// that `bunx projen` runs (and that the `sync` watcher invokes to re-synth).
|
|
836
|
+
// The runner choice is immaterial since the exec is reset to plain `bun` below;
|
|
837
|
+
// `nodejs()` avoids declaring a `ts-node`/`tsx` dependency.
|
|
792
838
|
new typescript.ProjenrcTs(project, {
|
|
793
|
-
runner: typescript.TypeScriptRunner.
|
|
839
|
+
runner: typescript.TypeScriptRunner.nodejs(),
|
|
794
840
|
});
|
|
795
|
-
//
|
|
796
|
-
//
|
|
797
|
-
//
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
//
|
|
801
|
-
//
|
|
802
|
-
|
|
803
|
-
project.defaultTask?.reset("tsx .projenrc.ts");
|
|
841
|
+
// bun runs `.projenrc.ts` directly (native TS, no loader to register). Reset to
|
|
842
|
+
// a plain `bun` exec rather than any wrapper: the default task is spawned by
|
|
843
|
+
// nested installs/synths, and a wrapper that exported `npm_config_*` broke them.
|
|
844
|
+
project.defaultTask?.reset("bun .projenrc.ts");
|
|
845
|
+
|
|
846
|
+
// Pin bun's hoisted linker workspace-wide (see RootBunfigFile) so a peer dep
|
|
847
|
+
// resolves to one copy and singletons/types stay coherent.
|
|
848
|
+
new RootBunfigFile(project);
|
|
804
849
|
|
|
805
850
|
// Only reached on a ROOT (early-returned above otherwise), so the root devDeps
|
|
806
851
|
// always apply; the self-dep is added only when the engine is an installed pkg.
|
|
@@ -863,11 +908,12 @@ function initProject(
|
|
|
863
908
|
eslint.addIgnorePattern(`${root}/openapi/**`);
|
|
864
909
|
eslint.addIgnorePattern(`${root}/**/index.ts`);
|
|
865
910
|
}
|
|
866
|
-
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
|
|
870
|
-
|
|
911
|
+
// The generated bun app scripts + unmanaged overrides live at the package root,
|
|
912
|
+
// outside any `src/**` tsconfig include, so the type-aware parser cannot resolve
|
|
913
|
+
// them to a project. ESLint still cannot parse them.
|
|
914
|
+
eslint.addIgnorePattern("**/dev.ts");
|
|
915
|
+
eslint.addIgnorePattern("**/build.ts");
|
|
916
|
+
for (const override of BUN_APP_OVERRIDES) {
|
|
871
917
|
eslint.addIgnorePattern(`**/${override}`);
|
|
872
918
|
}
|
|
873
919
|
// Codegen packages declare `codegen.inputs` via mixins after construction; ignore
|
package/src/release.ts
CHANGED
|
@@ -11,7 +11,44 @@ import { applyTasks, taskScript, type DBXToolsNodeProject } from "./project.ts";
|
|
|
11
11
|
|
|
12
12
|
const NODE_VERSION = "lts/*";
|
|
13
13
|
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
14
|
-
const
|
|
14
|
+
const BUN_VERSION = "1.3.14";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The `release` workflow's version-stamp + publish step, as a shell script.
|
|
18
|
+
*
|
|
19
|
+
* Bun has no `pnpm -r publish` equivalent, so this drives the engine's
|
|
20
|
+
* `tasks/publish.ts` (shipped in the engine tarball, run via bun): it reads the
|
|
21
|
+
* workspace members from the root `package.json`, stamps the tag version onto
|
|
22
|
+
* every manifest (rewriting `@dbx-tools/*` `workspace:*` sibling deps to
|
|
23
|
+
* `^<version>` so the tarballs resolve each other), then `bun publish`es each
|
|
24
|
+
* non-`private` package. `bun publish` substitutes `publishConfig` (the compiled
|
|
25
|
+
* `lib/` entry points) at pack time, runs `prepack` (compile) so `lib/` exists,
|
|
26
|
+
* and honors `NPM_CONFIG_PROVENANCE`.
|
|
27
|
+
*
|
|
28
|
+
* Two ways in: a pushed `<prefix>*` tag (the real release - `GITHUB_REF_NAME` is
|
|
29
|
+
* the version) and a manual `workflow_dispatch` (no tag, so a throwaway
|
|
30
|
+
* `0.0.0-dry.<run>` version is used and `--dry-run` is FORCED regardless of the
|
|
31
|
+
* input, since a dispatch never has a tag to publish as). The `dry_run` input
|
|
32
|
+
* (default true) is what lets a maintainer exercise the whole workflow - setup,
|
|
33
|
+
* install, stamp, compile, pack, validate - with nothing reaching npm.
|
|
34
|
+
*/
|
|
35
|
+
function BUN_PUBLISH_SCRIPT(tagPrefix: string, excludeDirs: readonly string[]): string {
|
|
36
|
+
const script = "node_modules/@dbx-tools/projen/tasks/publish.ts";
|
|
37
|
+
const excludes = excludeDirs.map((dir) => ` --exclude ${dir}`).join("");
|
|
38
|
+
return [
|
|
39
|
+
'if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then',
|
|
40
|
+
// A manual run has no tag: use a throwaway version and never really publish.
|
|
41
|
+
' VERSION="0.0.0-dry.${GITHUB_RUN_NUMBER}"',
|
|
42
|
+
" DRY_RUN=--dry-run",
|
|
43
|
+
"else",
|
|
44
|
+
` VERSION="\${GITHUB_REF_NAME#${tagPrefix}}"`,
|
|
45
|
+
// A tag push honors the input too, so a dry-run tag can be tested if wanted.
|
|
46
|
+
' DRY_RUN="${DRY_RUN_INPUT}"',
|
|
47
|
+
"fi",
|
|
48
|
+
"chmod -R u+w . || true",
|
|
49
|
+
`bun ${script} "$VERSION"${excludes} $DRY_RUN`,
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
15
52
|
|
|
16
53
|
interface PublishWorkflow {
|
|
17
54
|
readonly name: string;
|
|
@@ -24,17 +61,18 @@ interface PublishWorkflow {
|
|
|
24
61
|
function publishSetupSteps(): JobStep[] {
|
|
25
62
|
return [
|
|
26
63
|
{ name: "Checkout", uses: "actions/checkout@v6", with: { "fetch-depth": 0 } },
|
|
27
|
-
{ name: "Setup
|
|
64
|
+
{ name: "Setup Bun", uses: "oven-sh/setup-bun@v2", with: { "bun-version": BUN_VERSION } },
|
|
28
65
|
{
|
|
29
66
|
name: "Setup Node.js",
|
|
30
67
|
uses: "actions/setup-node@v6",
|
|
31
68
|
// setup-node writes the temporary npmrc that maps NODE_AUTH_TOKEN onto
|
|
32
69
|
// npmjs. Omitting this leaves the secret in the environment but gives npm
|
|
33
70
|
// no registry-scoped auth entry, and every publish fails with ENEEDAUTH.
|
|
71
|
+
// (Bun installs deps; publishing still goes through `npm publish`.)
|
|
34
72
|
with: { "node-version": NODE_VERSION, "registry-url": NPM_REGISTRY_URL },
|
|
35
73
|
},
|
|
36
|
-
//
|
|
37
|
-
{ name: "Install", run: "
|
|
74
|
+
// Bun's install; the lockfile may be absent or stale in CI so it is not frozen.
|
|
75
|
+
{ name: "Install", run: "bun install" },
|
|
38
76
|
];
|
|
39
77
|
}
|
|
40
78
|
|
|
@@ -160,12 +198,30 @@ export class DBXToolsRelease extends Component {
|
|
|
160
198
|
// the publish job below overrides it with the `id-token` it needs.
|
|
161
199
|
workflow.file?.addOverride("permissions", { contents: "read" });
|
|
162
200
|
workflow.on({ push: { tags: [`${tagPrefix}*`] } });
|
|
201
|
+
// Manual trigger for testing the workflow WITHOUT reaching npm: a
|
|
202
|
+
// `workflow_dispatch` run has no tag, so the publish script forces
|
|
203
|
+
// `--dry-run` (pack + validate only). The `dry_run` input (default true)
|
|
204
|
+
// additionally lets a tag push be dry-run on demand.
|
|
205
|
+
workflow.file?.addOverride("on.workflow_dispatch", {
|
|
206
|
+
inputs: {
|
|
207
|
+
dry_run: {
|
|
208
|
+
description: "Pack and validate but do not upload to npm",
|
|
209
|
+
type: "boolean",
|
|
210
|
+
default: true,
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
});
|
|
163
214
|
workflow.addJob("publish", {
|
|
164
215
|
runsOn: ["ubuntu-latest"],
|
|
165
216
|
// `id-token: write` lets npm mint the OIDC token for provenance attestation.
|
|
166
217
|
permissions: { contents: JobPermission.READ, idToken: JobPermission.WRITE },
|
|
167
218
|
timeoutMinutes: 30,
|
|
168
|
-
|
|
219
|
+
// `DRY_RUN_INPUT` is `--dry-run` when the dispatch input is true, else empty;
|
|
220
|
+
// the publish script also FORCES it on any `workflow_dispatch` run.
|
|
221
|
+
env: {
|
|
222
|
+
CI: "true",
|
|
223
|
+
DRY_RUN_INPUT: "${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}",
|
|
224
|
+
},
|
|
169
225
|
steps: [...publishSetupSteps(), ...steps],
|
|
170
226
|
...(workingDirectory ? { defaults: { run: { workingDirectory } } } : {}),
|
|
171
227
|
});
|
|
@@ -182,26 +238,25 @@ export class DBXToolsRelease extends Component {
|
|
|
182
238
|
name: "release",
|
|
183
239
|
tagPrefix: this.tagPrefix,
|
|
184
240
|
steps: [
|
|
185
|
-
// The pushed tag is the version: `<prefix>1.2.3` -> `1.2.3`.
|
|
186
|
-
// every package (manifests are projen-readonly, so unlock
|
|
241
|
+
// The pushed tag is the version: `<prefix>1.2.3` -> `1.2.3`. Stamp it on
|
|
242
|
+
// every workspace package (manifests are projen-readonly, so unlock
|
|
243
|
+
// first), rewriting `workspace:*` sibling deps to `^<version>` so the
|
|
244
|
+
// published tarballs resolve each other. `bun publish` honors
|
|
245
|
+
// `publishConfig` (compiled `lib/` entry points) and provenance.
|
|
187
246
|
{
|
|
188
|
-
name: "Set version from tag",
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
{
|
|
196
|
-
name: "Publish to npm",
|
|
197
|
-
// `pnpm -r publish` publishes every non-private package,
|
|
198
|
-
// rewriting `workspace:*` deps to the published version. Provenance is
|
|
199
|
-
// opt-in (omitted from each package's `publishConfig` so local
|
|
200
|
-
// publishes work); CI turns it on here via `npm_config_provenance`.
|
|
201
|
-
run: "pnpm -r publish --no-git-checks --access public",
|
|
247
|
+
name: "Set version from tag and publish",
|
|
248
|
+
// Exclude every standalone-release dir (e.g. `projen`): it publishes on
|
|
249
|
+
// its own `<prefix>-v*` tag via its own workflow, not the main `v*` one.
|
|
250
|
+
run: BUN_PUBLISH_SCRIPT(
|
|
251
|
+
this.tagPrefix,
|
|
252
|
+
this.standaloneReleases.map((s) => s.directory),
|
|
253
|
+
),
|
|
202
254
|
env: {
|
|
255
|
+
// `bun publish` authenticates via NPM_CONFIG_TOKEN (not NODE_AUTH_TOKEN,
|
|
256
|
+
// which is the `npm publish` convention). Set both so either tool works.
|
|
257
|
+
NPM_CONFIG_TOKEN: "${{ secrets.NPM_TOKEN }}",
|
|
203
258
|
NODE_AUTH_TOKEN: "${{ secrets.NPM_TOKEN }}",
|
|
204
|
-
|
|
259
|
+
NPM_CONFIG_PROVENANCE: "true",
|
|
205
260
|
},
|
|
206
261
|
},
|
|
207
262
|
],
|
|
@@ -210,34 +265,55 @@ export class DBXToolsRelease extends Component {
|
|
|
210
265
|
|
|
211
266
|
/**
|
|
212
267
|
* Emit a {@link StandaloneRelease}'s workflow: push `<prefix>1.2.3` and the
|
|
213
|
-
* single package in `directory`
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
268
|
+
* single package in `directory` is published at 1.2.3 via `bun publish`.
|
|
269
|
+
*
|
|
270
|
+
* `directory` (e.g. `projen/`) is a WORKSPACE MEMBER whose `@dbx-tools/*` deps
|
|
271
|
+
* are `workspace:*`. `bun publish` resolves those to whatever version its
|
|
272
|
+
* SIBLINGS carry (via the lockfile), so before publishing we set the version on
|
|
273
|
+
* the package AND its in-scope siblings, then refresh the lockfile - otherwise
|
|
274
|
+
* the published engine would depend on the siblings' on-disk `0.0.0`. The
|
|
275
|
+
* `Install` step already ran `bun install` from the repo root (the member
|
|
276
|
+
* subdir walks up to it), so the workspace is linked. The manifests are
|
|
277
|
+
* projen-readonly, hence the `chmod`. A manual `workflow_dispatch` run has no
|
|
278
|
+
* tag, so it uses a throwaway version and forces `--dry-run` (nothing to npm).
|
|
217
279
|
*/
|
|
218
280
|
private authorStandaloneReleaseWorkflow(
|
|
219
281
|
project: DBXToolsNodeProject,
|
|
220
282
|
{ name, directory, tagPrefix }: StandaloneRelease,
|
|
221
283
|
): void {
|
|
284
|
+
// The engine's release also stamps its in-scope siblings so `bun publish`
|
|
285
|
+
// resolves their `workspace:*` to the release version. Stamping the WHOLE
|
|
286
|
+
// workspace is simplest and harmless (only `directory` is published here).
|
|
287
|
+
const stampScript = "node_modules/@dbx-tools/projen/tasks/publish.ts";
|
|
222
288
|
this.authorPublishWorkflow(project, {
|
|
223
289
|
name,
|
|
224
290
|
tagPrefix,
|
|
225
|
-
workingDirectory: directory,
|
|
226
291
|
steps: [
|
|
227
|
-
// The pushed tag is the version: `<prefix>1.2.3` -> `1.2.3`. package.json
|
|
228
|
-
// is projen-generated read-only, so unlock it before `npm version` writes.
|
|
229
292
|
{
|
|
230
|
-
name: "Set version from tag",
|
|
293
|
+
name: "Set version from tag and publish",
|
|
231
294
|
run: [
|
|
232
|
-
"
|
|
233
|
-
|
|
295
|
+
'if [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then',
|
|
296
|
+
' VERSION="0.0.0-dry.${GITHUB_RUN_NUMBER}"',
|
|
297
|
+
" DRY_RUN=--dry-run",
|
|
298
|
+
"else",
|
|
299
|
+
` VERSION="\${GITHUB_REF_NAME#${tagPrefix}}"`,
|
|
300
|
+
' DRY_RUN="${DRY_RUN_INPUT}"',
|
|
301
|
+
"fi",
|
|
302
|
+
"chmod -R u+w . || true",
|
|
303
|
+
// Set the version across every member + refresh the lockfile (the
|
|
304
|
+
// publish task's stamp phase), so bun resolves the engine's
|
|
305
|
+
// `workspace:*` sibling deps to the release version at pack time.
|
|
306
|
+
`bun ${stampScript} "$VERSION" --stamp-only`,
|
|
307
|
+
// Then publish ONLY the standalone directory.
|
|
308
|
+
`cd ${directory} && bun publish --access public $DRY_RUN`,
|
|
234
309
|
].join("\n"),
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
310
|
+
env: {
|
|
311
|
+
// `bun publish` authenticates via NPM_CONFIG_TOKEN (not NODE_AUTH_TOKEN,
|
|
312
|
+
// which is the `npm publish` convention). Set both so either tool works.
|
|
313
|
+
NPM_CONFIG_TOKEN: "${{ secrets.NPM_TOKEN }}",
|
|
314
|
+
NODE_AUTH_TOKEN: "${{ secrets.NPM_TOKEN }}",
|
|
315
|
+
NPM_CONFIG_PROVENANCE: "true",
|
|
316
|
+
},
|
|
241
317
|
},
|
|
242
318
|
],
|
|
243
319
|
});
|
package/src/tags.ts
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { IMixin as ConstructsMixin } from "constructs";
|
|
17
17
|
import { javascript } from "projen";
|
|
18
|
+
import { BunBuildFile, BunDevServerFile, BunfigFile } from "./bun-app.ts";
|
|
18
19
|
import { create } from "./mixin.ts";
|
|
19
20
|
import {
|
|
20
21
|
addPackageFiles,
|
|
@@ -25,7 +26,6 @@ import {
|
|
|
25
26
|
srcModuleExports,
|
|
26
27
|
} from "./project.ts";
|
|
27
28
|
import * as projectPredicate from "./project-predicate.ts";
|
|
28
|
-
import { ViteConfigFile } from "./vite.ts";
|
|
29
29
|
|
|
30
30
|
/** Node compiler options: ES2022 lib + node types, deliberately no DOM. */
|
|
31
31
|
const NODE_COMPILER_OPTIONS: javascript.TypeScriptCompilerOptions = {
|
|
@@ -81,30 +81,42 @@ export const PACKAGE_TAG_MIXINS = {
|
|
|
81
81
|
"./package.json": "./package.json",
|
|
82
82
|
});
|
|
83
83
|
}),
|
|
84
|
-
// `app`: a full browser app built + served by
|
|
85
|
-
// entry). Self-contained React app: React + DOM lib + JSX +
|
|
86
|
-
//
|
|
87
|
-
// `
|
|
84
|
+
// `app`: a full browser app built + served by BUN (needs an `index.html`
|
|
85
|
+
// entry). Self-contained React app: React + DOM lib + JSX + bun's fullstack
|
|
86
|
+
// dev server (`dev.ts`, `Bun.serve` + HMR) and production bundle (`build.ts`,
|
|
87
|
+
// `Bun.build`). Tailwind v4 is compiled by `bun-plugin-tailwind` (wired in the
|
|
88
|
+
// generated `bunfig.toml`). No Vite.
|
|
88
89
|
app: create(projectPredicate.hasTag("app"), (p) => {
|
|
89
90
|
p.addDeps("react@catalog:", "react-dom@catalog:");
|
|
90
91
|
p.addDevDeps(
|
|
91
|
-
"vite@catalog:",
|
|
92
|
-
"@vitejs/plugin-react@catalog:",
|
|
93
92
|
"@types/react@catalog:",
|
|
94
93
|
"@types/react-dom@catalog:",
|
|
94
|
+
// The Tailwind plugin the dev server + build load. Tailwind itself is a
|
|
95
|
+
// catalog dep the app declares (it also owns the Tailwind entry CSS).
|
|
96
|
+
"bun-plugin-tailwind@catalog:",
|
|
95
97
|
);
|
|
96
98
|
applyCompilerOptions(p, {
|
|
97
99
|
target: "ES2022",
|
|
98
100
|
lib: [...DOM_LIB],
|
|
99
101
|
jsx: javascript.TypeScriptJsxMode.REACT_JSX,
|
|
100
|
-
types
|
|
102
|
+
// `@types/bun` (a root/subproject devDep) supplies the `Bun.*` globals the
|
|
103
|
+
// generated `dev.ts`/`build.ts` use; no `vite/client`.
|
|
104
|
+
types: ["bun"],
|
|
105
|
+
// `@/` -> `src/` alias, resolved by both tsc and bun's bundler (bun reads
|
|
106
|
+
// tsconfig `paths`). Replaces the old Vite `resolve.alias` for `@`.
|
|
107
|
+
baseUrl: ".",
|
|
108
|
+
paths: { "@/*": ["./src/*"] },
|
|
101
109
|
});
|
|
110
|
+
// bun runs the generated scripts directly. `build` resets the compile task so
|
|
111
|
+
// `compile` bundles with `Bun.build` rather than `tsc`.
|
|
102
112
|
applyTasks(p, {
|
|
103
|
-
dev: { exec: "
|
|
104
|
-
build: { exec: "
|
|
105
|
-
preview: { exec: "
|
|
113
|
+
dev: { exec: "bun dev.ts" },
|
|
114
|
+
build: { exec: "bun build.ts" },
|
|
115
|
+
preview: { exec: "bun dev.ts" },
|
|
106
116
|
});
|
|
107
|
-
new
|
|
117
|
+
new BunfigFile(p);
|
|
118
|
+
new BunDevServerFile(p);
|
|
119
|
+
new BunBuildFile(p);
|
|
108
120
|
// An app has a single root entry, not a component library's subpaths - so it
|
|
109
121
|
// replaces the `ui` tag's `./react`/`./styles.css` surface with a `.` root.
|
|
110
122
|
applyExports(p, {
|
|
@@ -147,9 +159,11 @@ export const PACKAGE_TAG_MIXINS = {
|
|
|
147
159
|
...NODE_COMPILER_OPTIONS,
|
|
148
160
|
experimentalDecorators: true,
|
|
149
161
|
});
|
|
162
|
+
// bun runs the server `.ts` directly (native TS, no tsx). `--watch` restarts
|
|
163
|
+
// on change - the tsx-watch replacement.
|
|
150
164
|
applyTasks(p, {
|
|
151
|
-
dev: { exec: "
|
|
152
|
-
start: { exec: "
|
|
165
|
+
dev: { exec: "bun --watch src/server.ts" },
|
|
166
|
+
start: { exec: "bun src/server.ts" },
|
|
153
167
|
});
|
|
154
168
|
}),
|
|
155
169
|
node: create(projectPredicate.hasTag("node"), (p) => {
|