@smoothbricks/cli 0.10.3 → 0.10.4

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.
Files changed (111) hide show
  1. package/README.md +9 -13
  2. package/dist/bun/preload.d.ts +13 -0
  3. package/dist/bun/preload.d.ts.map +1 -0
  4. package/dist/bun/preload.js +12 -0
  5. package/dist/cli.js +12 -4
  6. package/dist/generate/index.d.ts.map +1 -1
  7. package/dist/generate/index.js +0 -6
  8. package/dist/github-ci/index.d.ts.map +1 -1
  9. package/dist/github-ci/index.js +52 -16
  10. package/dist/github-ci/outputs.d.ts.map +1 -1
  11. package/dist/github-ci/outputs.js +1 -2
  12. package/dist/lib/cli-package.js +2 -2
  13. package/dist/lib/json.d.ts +118 -11
  14. package/dist/lib/json.d.ts.map +1 -1
  15. package/dist/lib/json.js +317 -29
  16. package/dist/lib/workspace.d.ts +7 -14
  17. package/dist/lib/workspace.d.ts.map +1 -1
  18. package/dist/lib/workspace.js +76 -82
  19. package/dist/monorepo/ci-workflow.d.ts +2 -0
  20. package/dist/monorepo/ci-workflow.d.ts.map +1 -1
  21. package/dist/monorepo/ci-workflow.js +27 -1
  22. package/dist/monorepo/git-config.js +2 -2
  23. package/dist/monorepo/index.d.ts +3 -1
  24. package/dist/monorepo/index.d.ts.map +1 -1
  25. package/dist/monorepo/index.js +6 -2
  26. package/dist/monorepo/lockfile.d.ts +13 -1
  27. package/dist/monorepo/lockfile.d.ts.map +1 -1
  28. package/dist/monorepo/lockfile.js +33 -21
  29. package/dist/monorepo/managed-files.d.ts +11 -0
  30. package/dist/monorepo/managed-files.d.ts.map +1 -1
  31. package/dist/monorepo/managed-files.js +52 -32
  32. package/dist/monorepo/package-policy.d.ts.map +1 -1
  33. package/dist/monorepo/package-policy.js +52 -45
  34. package/dist/monorepo/packed-manifest.d.ts +5 -2
  35. package/dist/monorepo/packed-manifest.d.ts.map +1 -1
  36. package/dist/monorepo/packed-manifest.js +16 -47
  37. package/dist/monorepo/packed-package.d.ts.map +1 -1
  38. package/dist/monorepo/packed-package.js +28 -16
  39. package/dist/monorepo/packs/index.d.ts.map +1 -1
  40. package/dist/monorepo/packs/index.js +13 -4
  41. package/dist/monorepo/publish-workflow.js +3 -1
  42. package/dist/monorepo/runtime.d.ts +15 -0
  43. package/dist/monorepo/runtime.d.ts.map +1 -1
  44. package/dist/monorepo/runtime.js +66 -12
  45. package/dist/monorepo/tool-validation.d.ts.map +1 -1
  46. package/dist/monorepo/tool-validation.js +32 -23
  47. package/dist/monorepo/wrangler.d.ts.map +1 -1
  48. package/dist/monorepo/wrangler.js +13 -13
  49. package/dist/nx/index.d.ts +9 -7
  50. package/dist/nx/index.d.ts.map +1 -1
  51. package/dist/nx/index.js +48 -31
  52. package/dist/pr/index.d.ts.map +1 -1
  53. package/dist/pr/index.js +28 -32
  54. package/dist/release/candidates.d.ts +3 -2
  55. package/dist/release/candidates.d.ts.map +1 -1
  56. package/dist/release/candidates.js +4 -5
  57. package/dist/release/index.d.ts +1 -0
  58. package/dist/release/index.d.ts.map +1 -1
  59. package/dist/release/index.js +82 -59
  60. package/dist/wrangler/prepare-env.d.ts +0 -1
  61. package/dist/wrangler/prepare-env.d.ts.map +1 -1
  62. package/dist/wrangler/prepare-env.js +100 -51
  63. package/dist/wrangler/scaffold.d.ts.map +1 -1
  64. package/dist/wrangler/scaffold.js +12 -12
  65. package/managed/raw/git-format-staged.yml +19 -1
  66. package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +2 -1
  67. package/managed/raw/tooling/direnv/merge-newer-pins.sh +3 -3
  68. package/managed/raw/tooling/direnv/setup-environment.ts +150 -19
  69. package/managed/raw/tooling/git-hooks/pre-commit.sh +0 -6
  70. package/managed/templates/github/actions/cache-node-modules/action.yml +5 -2
  71. package/managed/templates/github/actions/cache-ttsc-plugins/action.yml +19 -0
  72. package/managed/templates/github/actions/setup-devenv/action.yml +5 -0
  73. package/managed/templates/github/workflows/managed-files.yml +80 -0
  74. package/package.json +15 -4
  75. package/src/bun/preload.ts +12 -0
  76. package/src/cli.ts +19 -7
  77. package/src/generate/index.ts +0 -6
  78. package/src/github-ci/index.ts +49 -18
  79. package/src/github-ci/outputs.ts +1 -2
  80. package/src/lib/cli-package.ts +2 -2
  81. package/src/lib/json.ts +291 -32
  82. package/src/lib/workspace.ts +88 -100
  83. package/src/monorepo/__tests__/ci-workflow.test.ts +3 -3
  84. package/src/monorepo/ci-workflow.ts +27 -1
  85. package/src/monorepo/git-config.ts +2 -2
  86. package/src/monorepo/index.ts +6 -2
  87. package/src/monorepo/lockfile.test.ts +35 -36
  88. package/src/monorepo/lockfile.ts +48 -24
  89. package/src/monorepo/managed-files.test.ts +1 -0
  90. package/src/monorepo/managed-files.ts +57 -38
  91. package/src/monorepo/package-policy.test.ts +20 -50
  92. package/src/monorepo/package-policy.ts +76 -59
  93. package/src/monorepo/packed-manifest.ts +18 -52
  94. package/src/monorepo/packed-package.ts +43 -22
  95. package/src/monorepo/packs/index.ts +13 -4
  96. package/src/monorepo/publish-workflow.ts +3 -1
  97. package/src/monorepo/runtime.test.ts +42 -3
  98. package/src/monorepo/runtime.ts +90 -12
  99. package/src/monorepo/tool-validation.ts +35 -25
  100. package/src/monorepo/wrangler.test.ts +11 -15
  101. package/src/monorepo/wrangler.ts +15 -15
  102. package/src/nx/index.test.ts +9 -5
  103. package/src/nx/index.ts +69 -42
  104. package/src/pr/index.ts +42 -36
  105. package/src/release/__tests__/candidates.test.ts +5 -4
  106. package/src/release/__tests__/trust-publisher.test.ts +7 -0
  107. package/src/release/candidates.ts +10 -17
  108. package/src/release/index.ts +104 -73
  109. package/src/wrangler/prepare-env.ts +75 -54
  110. package/src/wrangler/scaffold.test.ts +9 -12
  111. package/src/wrangler/scaffold.ts +13 -13
@@ -5,27 +5,36 @@ import { escapeRegex, getWorkspacePackages } from '../lib/workspace.js';
5
5
 
6
6
  export interface SyncBunLockfileVersionsOptions {
7
7
  log?: boolean;
8
- /** `git add` bun.lock after rewriting it, for the pre-commit self-heal path. */
8
+ /** `git add` bun.lock when versions were resynced. */
9
9
  stage?: boolean;
10
+ /**
11
+ * `install` (default for validation): lockfile must match package.json.
12
+ * `publish`: rewrite unpublished prerelease package.json versions to the last
13
+ * stable git tag so `bun pm pack` embeds installable dependency versions.
14
+ */
15
+ mode?: 'install' | 'publish';
10
16
  }
11
17
 
12
- // Temporary Bun workaround. Delete this sync function, validateBunLockfileVersions,
13
- // the `smoo monorepo sync-bun-lockfile-versions` command, and the matching Nx
14
- // versionActions hook once supported Bun versions stop leaving workspace package
15
- // versions stale in bun.lock after manifest bumps. Until then, `bun pm pack`
16
- // rewrites `workspace:*` dependencies using those stale lockfile versions instead
17
- // of the current package.json versions. Track removal against:
18
+ // Temporary Bun workaround. Delete once supported Bun versions stop leaving
19
+ // workspace package versions stale in bun.lock after manifest bumps, and stop
20
+ // resolving `workspace:*` from the lockfile during `bun pm pack`:
18
21
  // - https://github.com/oven-sh/bun/issues/18906
19
22
  // - https://github.com/oven-sh/bun/issues/20477
20
23
  // - https://github.com/oven-sh/bun/issues/20829
21
24
  //
22
- // Any `bun install` rewrites the workspace versions from package.json, reverting
23
- // this sync between releases. The pre-commit hook therefore runs
24
- // `smoo monorepo sync-bun-lockfile-versions --stage` on every commit so drift is
25
- // healed at the commit that would otherwise carry it — validation must never
26
- // fail a committer for drift a routine `bun install` introduced.
25
+ // Two modes, because one lockfile serves two jobs:
26
+ //
27
+ // 1) install / frozen CI → lockfile package.json (including -next)
28
+ // 2) pre-publish pack → for package.json prereleases that were never published
29
+ // (post-release "prepare next"), lockfile entry := last
30
+ // stable tag so a releasing package does not embed an
31
+ // unpublished -next dependency version.
32
+ //
33
+ // Do not run publish-mode rewrite in day-to-day validate or pre-commit: bun install
34
+ // rewrites lockfile back to package.json and frozen CI then fails.
27
35
  export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVersionsOptions = {}): number {
28
36
  const log = options.log ?? true;
37
+ const mode = options.mode ?? 'publish';
29
38
  const lockfilePath = join(root, 'bun.lock');
30
39
  if (!existsSync(lockfilePath)) {
31
40
  throw new Error('bun.lock not found');
@@ -34,13 +43,7 @@ export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVe
34
43
  let lockfile = readFileSync(lockfilePath, 'utf8');
35
44
  let updated = 0;
36
45
  for (const pkg of packages) {
37
- // If the package.json version is a prerelease (e.g. 0.2.2-next.0) it may
38
- // never have been published. Use the latest stable git tag version so
39
- // that `bun pm pack` writes an installable dependency range for consumers.
40
- const targetVersion = pkg.version.includes('-')
41
- ? (latestStableTagVersion(root, pkg.projectName) ?? pkg.version)
42
- : pkg.version;
43
-
46
+ const targetVersion = lockfileTargetVersion(root, pkg.projectName, pkg.version, mode);
44
47
  const relativePath = pkg.path.replaceAll('\\', '/');
45
48
  const escaped = escapeRegex(relativePath);
46
49
  const pattern = new RegExp(`("${escaped}":\\s*\\{[^}]*"version":\\s*")([^"]+)(")`);
@@ -60,7 +63,10 @@ export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVe
60
63
  }
61
64
  lockfile = lockfile.replace(pattern, `$1${targetVersion}$3`);
62
65
  if (log) {
63
- const suffix = targetVersion !== pkg.version ? ` (latest stable tag; package.json has ${pkg.version})` : '';
66
+ const suffix =
67
+ mode === 'publish' && targetVersion !== pkg.version
68
+ ? ` (latest stable tag; package.json has ${pkg.version})`
69
+ : '';
64
70
  console.log(`fix: ${relativePath}: ${lockVersion} -> ${targetVersion}${suffix}`);
65
71
  }
66
72
  updated++;
@@ -81,6 +87,7 @@ export function syncBunLockfileVersions(root: string, options: SyncBunLockfileVe
81
87
  return updated;
82
88
  }
83
89
 
90
+ /** Install/CI invariant: bun.lock workspace versions match package.json. */
84
91
  export function validateBunLockfileVersions(root: string): number {
85
92
  const lockfilePath = join(root, 'bun.lock');
86
93
  if (!existsSync(lockfilePath)) {
@@ -91,10 +98,7 @@ export function validateBunLockfileVersions(root: string): number {
91
98
  const lockfile = readFileSync(lockfilePath, 'utf8');
92
99
  let failures = 0;
93
100
  for (const pkg of packages) {
94
- const targetVersion = pkg.version.includes('-')
95
- ? (latestStableTagVersion(root, pkg.projectName) ?? pkg.version)
96
- : pkg.version;
97
-
101
+ const targetVersion = pkg.version;
98
102
  const relativePath = pkg.path.replaceAll('\\', '/');
99
103
  const escaped = escapeRegex(relativePath);
100
104
  const pattern = new RegExp(`("${escaped}":\\s*\\{[^}]*"version":\\s*")([^"]+)(")`);
@@ -116,6 +120,26 @@ export function validateBunLockfileVersions(root: string): number {
116
120
  return failures;
117
121
  }
118
122
 
123
+ /**
124
+ * Version Bun should embed for a workspace dependency when packing for publish.
125
+ * Unpublished package.json prereleases (prepare-next) map to the last stable tag.
126
+ */
127
+ export function publishPackDependencyVersion(root: string, projectName: string, packageVersion: string): string {
128
+ return lockfileTargetVersion(root, projectName, packageVersion, 'publish');
129
+ }
130
+
131
+ function lockfileTargetVersion(
132
+ root: string,
133
+ projectName: string,
134
+ packageVersion: string,
135
+ mode: 'install' | 'publish',
136
+ ): string {
137
+ if (mode === 'install' || !packageVersion.includes('-')) {
138
+ return packageVersion;
139
+ }
140
+ return latestStableTagVersion(root, projectName) ?? packageVersion;
141
+ }
142
+
119
143
  function latestStableTagVersion(root: string, projectName: string): string | null {
120
144
  try {
121
145
  const output = execSync(`git tag --list '${projectName}@*' --sort=-v:refname`, {
@@ -22,6 +22,7 @@ const NODE_MODULES_CACHE_KEY = "${{ hashFiles('bun.lock', 'package.json', 'packa
22
22
  const CACHE_ACTIONS = [
23
23
  { name: 'cache-nix-devenv', osKeyLines: 6 },
24
24
  { name: 'cache-node-modules', osKeyLines: 2 },
25
+ { name: 'cache-ttsc-plugins', osKeyLines: 2 },
25
26
  { name: 'cache-nx', osKeyLines: 2 },
26
27
  ] as const;
27
28
 
@@ -1,8 +1,9 @@
1
1
  import { execFileSync } from 'node:child_process';
2
- import { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { appendFileSync, existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { dirname, join, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { PLATFORM_TARGET_GLOBS } from '@smoothbricks/nx-plugin/workspace-config-policy';
6
+ import { type PackageJson, parseNxProjectJsonText, parseStringArrayText } from '../lib/json.js';
6
7
  import { listReleasePackages, readPackageJson } from '../lib/workspace.js';
7
8
  import { renderCiWorkflowYaml } from './ci-workflow.js';
8
9
  import { renderPublishWorkflowYaml } from './publish-workflow.js';
@@ -209,6 +210,11 @@ const managedFiles: ManagedFile[] = [
209
210
  target: '.github/workflows/publish.yml',
210
211
  releasePackagesOnly: true,
211
212
  },
213
+ {
214
+ kind: 'template',
215
+ source: 'github/workflows/managed-files.yml',
216
+ target: '.github/workflows/managed-files.yml',
217
+ },
212
218
  {
213
219
  kind: 'template',
214
220
  source: 'github/actions/cache-nix-devenv/action.yml',
@@ -229,6 +235,11 @@ const managedFiles: ManagedFile[] = [
229
235
  source: 'github/actions/cache-node-modules/action.yml',
230
236
  target: '.github/actions/cache-node-modules/action.yml',
231
237
  },
238
+ {
239
+ kind: 'template',
240
+ source: 'github/actions/cache-ttsc-plugins/action.yml',
241
+ target: '.github/actions/cache-ttsc-plugins/action.yml',
242
+ },
232
243
  {
233
244
  kind: 'template',
234
245
  source: 'github/actions/cache-nx/action.yml',
@@ -348,8 +359,8 @@ function readResolvedNxTargetNames(root: string): string[] {
348
359
  encoding: 'utf8',
349
360
  stdio: ['ignore', 'pipe', 'inherit'],
350
361
  });
351
- const projects: unknown = JSON.parse(output);
352
- if (!Array.isArray(projects) || !projects.every((project) => typeof project === 'string')) {
362
+ const projects = parseStringArrayText(output);
363
+ if (!projects) {
353
364
  return [];
354
365
  }
355
366
  const targetNames = new Set<string>();
@@ -359,8 +370,8 @@ function readResolvedNxTargetNames(root: string): string[] {
359
370
  encoding: 'utf8',
360
371
  stdio: ['ignore', 'pipe', 'inherit'],
361
372
  });
362
- const projectJson: unknown = JSON.parse(projectOutput);
363
- const targets = recordValue(recordValue(projectJson)?.targets);
373
+ const projectJson = parseNxProjectJsonText(projectOutput);
374
+ const targets = projectJson?.targets;
364
375
  if (targets) {
365
376
  for (const targetName of Object.keys(targets)) {
366
377
  targetNames.add(targetName);
@@ -383,8 +394,8 @@ function getDeployTargetInfo(root: string, configuration: string): DeployTargetI
383
394
  encoding: 'utf8',
384
395
  stdio: ['ignore', 'pipe', 'inherit'],
385
396
  });
386
- const projects: unknown = JSON.parse(output);
387
- if (!Array.isArray(projects) || !projects.every((project) => typeof project === 'string')) {
397
+ const projects = parseStringArrayText(output);
398
+ if (!projects) {
388
399
  return { exists: false };
389
400
  }
390
401
  let exists = false;
@@ -406,47 +417,25 @@ function nxDeployTarget(root: string, project: string, configuration: string): D
406
417
  encoding: 'utf8',
407
418
  stdio: ['ignore', 'pipe', 'inherit'],
408
419
  });
409
- const parsed: unknown = JSON.parse(output);
410
- const projectJson = recordValue(parsed);
411
- const targets = recordValue(projectJson?.targets);
412
- const deploy = recordValue(targets?.deploy);
413
- const configurations = recordValue(deploy?.configurations);
414
- const config = recordValue(configurations?.[configuration]);
420
+ const projectJson = parseNxProjectJsonText(output);
421
+ const deploy = projectJson?.targets?.deploy;
422
+ const config = deploy?.configurations?.[configuration];
415
423
  if (!config) {
416
424
  return { exists: false };
417
425
  }
418
- const command = deployCommand(deploy, config);
426
+ const commandValue = config.command ?? config.options?.command ?? deploy?.options?.command;
427
+ const command = typeof commandValue === 'string' ? commandValue : '';
419
428
  return { exists: true, provider: command.includes('wrangler ') ? 'cloudflare' : undefined };
420
429
  }
421
430
 
422
- function deployCommand(deploy: Record<string, unknown> | undefined, config: Record<string, unknown>): string {
423
- const command = stringValue(config.command) ?? stringValue(recordValue(config.options)?.command);
424
- return command ?? stringValue(recordValue(deploy?.options)?.command) ?? '';
425
- }
426
-
427
- function stringValue(value: unknown): string | undefined {
428
- return typeof value === 'string' ? value : undefined;
429
- }
430
-
431
- function getCiPushBranches(packageJson: unknown): string[] {
431
+ function getCiPushBranches(packageJson: PackageJson | null | undefined): string[] {
432
432
  const configured = readCiPushBranches(packageJson);
433
433
  return configured.length > 0 ? configured : ['main'];
434
434
  }
435
435
 
436
- function readCiPushBranches(packageJson: unknown): string[] {
437
- const rootPackage = recordValue(packageJson);
438
- const smoo = recordValue(rootPackage?.smoo);
439
- const github = recordValue(smoo?.github);
440
- const branches = Array.isArray(github?.pushBranches) ? github.pushBranches : [];
441
- return branches.filter((branch): branch is string => typeof branch === 'string' && branch.length > 0);
442
- }
443
-
444
- function recordValue(value: unknown): Record<string, unknown> | undefined {
445
- return isRecord(value) ? value : undefined;
446
- }
447
-
448
- function isRecord(value: unknown): value is Record<string, unknown> {
449
- return value !== null && typeof value === 'object' && !Array.isArray(value);
436
+ function readCiPushBranches(packageJson: PackageJson | null | undefined): string[] {
437
+ const branches = packageJson?.smoo?.github?.pushBranches ?? [];
438
+ return branches.filter((branch) => branch.length > 0);
450
439
  }
451
440
 
452
441
  function renderYamlFlowList(values: string[]): string {
@@ -473,3 +462,33 @@ export function validateManagedFiles(root: string): number {
473
462
  }
474
463
  return failures;
475
464
  }
465
+
466
+ /**
467
+ * Non-blocking drift report: prints the per-file table and surfaces drift as
468
+ * GitHub Actions warning annotations (plain stderr elsewhere) without failing
469
+ * the run. Managed-file drift is derived state with its own remediation flow
470
+ * (the persistent managed-files PR); only `monorepo check` without --warn and
471
+ * PR-scoped gates treat it as an error.
472
+ *
473
+ * Under GitHub Actions the drifted-file count is published as the step output
474
+ * `drifted`, so downstream steps gate declaratively instead of parsing logs.
475
+ */
476
+ export function warnOnManagedFileDrift(root: string): void {
477
+ const results = applyManagedFiles(root, 'check');
478
+ printResults(results);
479
+ const drifted = results.filter((result) => result.action === 'drifted');
480
+ if (process.env.GITHUB_OUTPUT) {
481
+ appendFileSync(process.env.GITHUB_OUTPUT, `drifted=${drifted.length}\n`);
482
+ }
483
+ if (drifted.length === 0) {
484
+ return;
485
+ }
486
+ if (process.env.GITHUB_ACTIONS === 'true') {
487
+ for (const result of drifted) {
488
+ console.log(
489
+ `::warning title=Managed file drift::${result.target} drifted from the @smoothbricks/cli template; run 'smoo monorepo update'`,
490
+ );
491
+ }
492
+ }
493
+ console.error(`${drifted.length} managed monorepo file(s) drifted (non-blocking). Run: smoo monorepo update`);
494
+ }
@@ -262,7 +262,7 @@ describe('workspace package script policy', () => {
262
262
  try {
263
263
  expect(validateWorkspaceDependencies(root)).toBe(2);
264
264
 
265
- const resolvedTargetsByProject = new Map([['native', new Set(['build', 'tsc-js', 'zig-wasm'])]]);
265
+ const resolvedTargetsByProject = new Map([['native', new Set(['build', 'tsc-js', 'tsdown-js'])]]);
266
266
  applyWorkspaceDependencyDefaults(root, { resolvedTargetsByProject });
267
267
 
268
268
  const native = await readJson(join(root, 'packages/native/package.json'));
@@ -284,17 +284,17 @@ describe('workspace package script policy', () => {
284
284
  dependencies: { '@smoothbricks/lib': 'workspace:*' },
285
285
  scripts: {
286
286
  'build:custom': 'nx run native:build:custom',
287
- 'build:zig': 'nx run native:build:zig',
287
+ 'build:bundle': 'nx run native:build:bundle',
288
288
  'build:ts': 'nx run native:build:ts',
289
289
  },
290
290
  nx: {
291
291
  name: 'native',
292
292
  targets: {
293
- build: { dependsOn: ['^build', 'build:ts', 'build:zig', 'build:custom'] },
293
+ build: { dependsOn: ['^build', 'build:ts', 'build:bundle', 'build:custom'] },
294
294
  'build:custom': {},
295
- 'build:zig': {
295
+ 'build:bundle': {
296
296
  executor: 'nx:run-commands',
297
- options: { command: 'zig build wasm', cwd: '{projectRoot}' },
297
+ options: { command: 'tsdown', cwd: '{projectRoot}' },
298
298
  },
299
299
  'build:ts': {
300
300
  executor: 'nx:run-commands',
@@ -307,25 +307,21 @@ describe('workspace package script policy', () => {
307
307
  });
308
308
  try {
309
309
  await writeJson(join(root, 'packages/native/tsconfig.lib.json'), {});
310
- await writeFile(
311
- join(root, 'packages/native/build.zig'),
312
- 'pub fn build(b: *std.Build) void { _ = b.step("wasm", "Build wasm"); }\n',
313
- );
314
310
  expect(validateWorkspaceDependencies(root)).toBe(6);
315
311
 
316
- const resolvedTargetsByProject = new Map([['native', new Set(['build', 'custom', 'tsc-js', 'zig-wasm'])]]);
312
+ const resolvedTargetsByProject = new Map([['native', new Set(['build', 'custom', 'tsc-js', 'tsdown-js'])]]);
317
313
  applyWorkspaceDependencyDefaults(root, { resolvedTargetsByProject });
318
314
 
319
315
  const native = await readJson(join(root, 'packages/native/package.json'));
320
316
  expect(native.scripts).toEqual({
321
317
  'build:custom': 'nx run native:custom',
322
- 'build:zig': 'nx run native:zig-wasm',
318
+ 'build:bundle': 'nx run native:tsdown-js',
323
319
  'build:ts': 'nx run native:tsc-js',
324
320
  });
325
321
  expect(native.nx).toEqual({
326
322
  name: 'native',
327
323
  targets: {
328
- build: { dependsOn: ['^build', 'tsc-js', 'zig-wasm', 'custom'] },
324
+ build: { dependsOn: ['^build', 'tsc-js', 'tsdown-js', 'custom'] },
329
325
  },
330
326
  });
331
327
  expect(validateWorkspaceDependencies(root, { resolvedTargetsByProject })).toBe(0);
@@ -344,7 +340,7 @@ describe('workspace package script policy', () => {
344
340
  nx: {
345
341
  name: 'native',
346
342
  targets: {
347
- build: { executor: 'nx:noop', dependsOn: ['^build', 'tsc-js', 'zig-wasm', 'custom'] },
343
+ build: { executor: 'nx:noop', dependsOn: ['^build', 'tsc-js', 'tsdown-js', 'custom'] },
348
344
  },
349
345
  },
350
346
  },
@@ -352,14 +348,10 @@ describe('workspace package script policy', () => {
352
348
  });
353
349
  try {
354
350
  await writeJson(join(root, 'packages/native/tsconfig.lib.json'), {});
355
- await writeFile(
356
- join(root, 'packages/native/build.zig'),
357
- 'pub fn build(b: *std.Build) void { _ = b.step("wasm", "Build wasm"); }\n',
358
- );
359
351
  const resolvedTargetsByProject = new Map([
360
352
  [
361
353
  'native',
362
- { targets: new Set(['build', 'tsc-js', 'zig-wasm']), buildDependsOn: ['^build', 'tsc-js', 'zig-wasm'] },
354
+ { targets: new Set(['build', 'tsc-js', 'tsdown-js']), buildDependsOn: ['^build', 'tsc-js', 'tsdown-js'] },
363
355
  ],
364
356
  ]);
365
357
 
@@ -369,7 +361,7 @@ describe('workspace package script policy', () => {
369
361
  expect(native.nx).toEqual({
370
362
  name: 'native',
371
363
  targets: {
372
- build: { executor: 'nx:noop', dependsOn: ['^build', 'tsc-js', 'zig-wasm', 'custom'] },
364
+ build: { executor: 'nx:noop', dependsOn: ['^build', 'tsc-js', 'tsdown-js', 'custom'] },
373
365
  },
374
366
  });
375
367
  } finally {
@@ -389,8 +381,8 @@ describe('workspace package script policy', () => {
389
381
  targets: {
390
382
  build: {
391
383
  executor: 'nx:run-commands',
392
- options: { command: 'zig build wasm', cwd: '{projectRoot}' },
393
- dependsOn: ['^build', 'zig-wasm'],
384
+ options: { command: 'tsdown', cwd: '{projectRoot}' },
385
+ dependsOn: ['^build', 'tsdown-js'],
394
386
  },
395
387
  },
396
388
  },
@@ -398,12 +390,8 @@ describe('workspace package script policy', () => {
398
390
  ],
399
391
  });
400
392
  try {
401
- await writeFile(
402
- join(root, 'packages/native/build.zig'),
403
- 'pub fn build(b: *std.Build) void { _ = b.step("wasm", "Build wasm"); }\n',
404
- );
405
393
  const resolvedTargetsByProject = new Map([
406
- ['native', { targets: new Set(['build', 'zig-wasm']), buildDependsOn: ['^build', 'zig-wasm'] }],
394
+ ['native', { targets: new Set(['build', 'tsdown-js']), buildDependsOn: ['^build', 'tsdown-js'] }],
407
395
  ]);
408
396
 
409
397
  applyWorkspaceDependencyDefaults(root, { resolvedTargetsByProject });
@@ -414,8 +402,8 @@ describe('workspace package script policy', () => {
414
402
  targets: {
415
403
  build: {
416
404
  executor: 'nx:run-commands',
417
- options: { command: 'zig build wasm', cwd: '{projectRoot}' },
418
- dependsOn: ['^build', 'zig-wasm'],
405
+ options: { command: 'tsdown', cwd: '{projectRoot}' },
406
+ dependsOn: ['^build', 'tsdown-js'],
419
407
  },
420
408
  },
421
409
  });
@@ -434,7 +422,7 @@ describe('workspace package script policy', () => {
434
422
  nx: {
435
423
  name: 'native',
436
424
  targets: {
437
- build: { executor: 'nx:noop', dependsOn: ['^build', 'tsc-js', 'zig-wasm'] },
425
+ build: { executor: 'nx:noop', dependsOn: ['^build', 'tsc-js', 'tsdown-js'] },
438
426
  },
439
427
  },
440
428
  },
@@ -444,7 +432,7 @@ describe('workspace package script policy', () => {
444
432
  const resolvedTargetsByProject = new Map([
445
433
  [
446
434
  'native',
447
- { targets: new Set(['build', 'tsc-js', 'zig-wasm']), buildDependsOn: ['^build', 'tsc-js', 'zig-wasm'] },
435
+ { targets: new Set(['build', 'tsc-js', 'tsdown-js']), buildDependsOn: ['^build', 'tsc-js', 'tsdown-js'] },
448
436
  ],
449
437
  ]);
450
438
 
@@ -498,7 +486,7 @@ describe('workspace package script policy', () => {
498
486
  });
499
487
  try {
500
488
  const resolvedTargetsByProject = new Map([
501
- ['native', { targets: new Set(['build', 'tsc-js', 'zig-wasm']), buildDependsOn: buildOutputDependencies }],
489
+ ['native', { targets: new Set(['build', 'tsc-js', 'tsdown-js']), buildDependsOn: buildOutputDependencies }],
502
490
  ]);
503
491
 
504
492
  applyWorkspaceDependencyDefaults(root, { resolvedTargetsByProject });
@@ -558,20 +546,6 @@ describe('workspace package script policy', () => {
558
546
  }
559
547
  });
560
548
 
561
- it('rejects build.zig without steps', async () => {
562
- const root = await createWorkspace({
563
- rootName: '@smoothbricks/codebase',
564
- packages: [{ dir: 'native', name: '@smoothbricks/native', nx: { name: 'native' } }],
565
- });
566
- try {
567
- await writeFile(join(root, 'packages/native/build.zig'), 'pub fn build(b: *std.Build) void { _ = b; }\n');
568
-
569
- expect(validateWorkspaceDependencies(root)).toBe(1);
570
- } finally {
571
- await rm(root, { recursive: true, force: true });
572
- }
573
- });
574
-
575
549
  it('rejects old test tsconfig output for packages with test runners', async () => {
576
550
  const root = await createWorkspace({
577
551
  rootName: '@smoothbricks/codebase',
@@ -728,17 +702,13 @@ describe('workspace package script policy', () => {
728
702
  }
729
703
  });
730
704
 
731
- it('accepts noEmit test tsconfig and build.zig with an explicit step', async () => {
705
+ it('accepts a noEmit test tsconfig', async () => {
732
706
  const root = await createWorkspace({
733
707
  rootName: '@smoothbricks/codebase',
734
708
  packages: [{ dir: 'native', name: '@smoothbricks/native', nx: { name: 'native', targets: { lint: {} } } }],
735
709
  });
736
710
  try {
737
711
  await writeJson(join(root, 'packages/native/tsconfig.test.json'), { compilerOptions: { noEmit: true } });
738
- await writeFile(
739
- join(root, 'packages/native/build.zig'),
740
- 'pub fn build(b: *std.Build) void { _ = b.step("build", "Build native artifact"); }\n',
741
- );
742
712
 
743
713
  expect(validateWorkspaceDependencies(root)).toBe(0);
744
714
  } finally {