@smoothbricks/cli 0.10.3 → 0.10.5
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 +9 -13
- package/dist/bun/preload.d.ts +13 -0
- package/dist/bun/preload.d.ts.map +1 -0
- package/dist/bun/preload.js +12 -0
- package/dist/cli.js +13 -5
- package/dist/generate/index.d.ts.map +1 -1
- package/dist/generate/index.js +0 -6
- package/dist/github-ci/index.d.ts.map +1 -1
- package/dist/github-ci/index.js +52 -16
- package/dist/github-ci/outputs.d.ts.map +1 -1
- package/dist/github-ci/outputs.js +1 -2
- package/dist/lib/cli-package.js +2 -2
- package/dist/lib/json.d.ts +120 -11
- package/dist/lib/json.d.ts.map +1 -1
- package/dist/lib/json.js +319 -29
- package/dist/lib/workspace.d.ts +7 -14
- package/dist/lib/workspace.d.ts.map +1 -1
- package/dist/lib/workspace.js +76 -82
- package/dist/monorepo/ci-workflow.d.ts +2 -0
- package/dist/monorepo/ci-workflow.d.ts.map +1 -1
- package/dist/monorepo/ci-workflow.js +27 -1
- package/dist/monorepo/git-config.js +2 -2
- package/dist/monorepo/index.d.ts +4 -2
- package/dist/monorepo/index.d.ts.map +1 -1
- package/dist/monorepo/index.js +19 -3
- package/dist/monorepo/lockfile.d.ts +14 -1
- package/dist/monorepo/lockfile.d.ts.map +1 -1
- package/dist/monorepo/lockfile.js +33 -21
- package/dist/monorepo/managed-files.d.ts +11 -0
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +57 -32
- package/dist/monorepo/package-policy.d.ts.map +1 -1
- package/dist/monorepo/package-policy.js +52 -45
- package/dist/monorepo/packed-manifest.d.ts +5 -2
- package/dist/monorepo/packed-manifest.d.ts.map +1 -1
- package/dist/monorepo/packed-manifest.js +16 -47
- package/dist/monorepo/packed-package.d.ts.map +1 -1
- package/dist/monorepo/packed-package.js +28 -16
- package/dist/monorepo/packs/index.d.ts.map +1 -1
- package/dist/monorepo/packs/index.js +14 -5
- package/dist/monorepo/publish-workflow.js +3 -1
- package/dist/monorepo/runtime.d.ts +15 -0
- package/dist/monorepo/runtime.d.ts.map +1 -1
- package/dist/monorepo/runtime.js +66 -12
- package/dist/monorepo/tool-validation.d.ts +2 -2
- package/dist/monorepo/tool-validation.d.ts.map +1 -1
- package/dist/monorepo/tool-validation.js +141 -38
- package/dist/monorepo/wrangler.d.ts.map +1 -1
- package/dist/monorepo/wrangler.js +13 -13
- package/dist/nx/index.d.ts +9 -7
- package/dist/nx/index.d.ts.map +1 -1
- package/dist/nx/index.js +48 -31
- package/dist/pr/index.d.ts.map +1 -1
- package/dist/pr/index.js +28 -32
- package/dist/release/candidates.d.ts +3 -2
- package/dist/release/candidates.d.ts.map +1 -1
- package/dist/release/candidates.js +4 -5
- package/dist/release/index.d.ts +1 -0
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +88 -59
- package/dist/wrangler/prepare-env.d.ts +0 -1
- package/dist/wrangler/prepare-env.d.ts.map +1 -1
- package/dist/wrangler/prepare-env.js +100 -51
- package/dist/wrangler/scaffold.d.ts.map +1 -1
- package/dist/wrangler/scaffold.js +12 -12
- package/managed/raw/envrc +5 -3
- package/managed/raw/git-format-staged.yml +19 -1
- package/managed/raw/patches/ttsc@0.19.3.patch +67 -0
- package/managed/raw/tooling/direnv/github-actions-bootstrap.sh +2 -1
- package/managed/raw/tooling/direnv/merge-newer-pins.sh +3 -3
- package/managed/raw/tooling/direnv/setup-environment.ts +170 -19
- package/managed/raw/tooling/git-hooks/pre-commit.sh +0 -6
- package/managed/templates/github/actions/cache-node-modules/action.yml +5 -2
- package/managed/templates/github/actions/cache-ttsc-plugins/action.yml +19 -0
- package/managed/templates/github/actions/setup-devenv/action.yml +5 -0
- package/managed/templates/github/workflows/managed-files.yml +80 -0
- package/package.json +15 -4
- package/src/bun/preload.ts +12 -0
- package/src/cli.ts +20 -8
- package/src/generate/index.ts +0 -6
- package/src/github-ci/index.ts +49 -18
- package/src/github-ci/outputs.ts +1 -2
- package/src/lib/cli-package.ts +2 -2
- package/src/lib/json.ts +293 -32
- package/src/lib/workspace.ts +88 -100
- package/src/monorepo/__tests__/ci-workflow.test.ts +3 -3
- package/src/monorepo/ci-workflow.ts +27 -1
- package/src/monorepo/git-config.ts +2 -2
- package/src/monorepo/index.ts +19 -3
- package/src/monorepo/lockfile.test.ts +35 -36
- package/src/monorepo/lockfile.ts +49 -24
- package/src/monorepo/managed-files.test.ts +1 -0
- package/src/monorepo/managed-files.ts +62 -38
- package/src/monorepo/package-policy.test.ts +20 -50
- package/src/monorepo/package-policy.ts +76 -59
- package/src/monorepo/packed-manifest.ts +18 -52
- package/src/monorepo/packed-package.ts +43 -22
- package/src/monorepo/packs/index.ts +14 -5
- package/src/monorepo/publish-workflow.ts +3 -1
- package/src/monorepo/runtime.test.ts +42 -3
- package/src/monorepo/runtime.ts +90 -12
- package/src/monorepo/tool-validation.test.ts +38 -16
- package/src/monorepo/tool-validation.ts +149 -41
- package/src/monorepo/wrangler.test.ts +11 -15
- package/src/monorepo/wrangler.ts +15 -15
- package/src/nx/index.test.ts +9 -5
- package/src/nx/index.ts +69 -42
- package/src/pr/index.ts +42 -36
- package/src/release/__tests__/candidates.test.ts +5 -4
- package/src/release/__tests__/trust-publisher.test.ts +7 -0
- package/src/release/candidates.ts +10 -17
- package/src/release/index.ts +110 -73
- package/src/wrangler/prepare-env.ts +75 -54
- package/src/wrangler/scaffold.test.ts +9 -12
- package/src/wrangler/scaffold.ts +13 -13
|
@@ -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 { 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';
|
|
@@ -145,6 +146,11 @@ const managedFiles = [
|
|
|
145
146
|
target: 'tooling/direnv/merge-newer-pins.sh',
|
|
146
147
|
executable: true,
|
|
147
148
|
},
|
|
149
|
+
{
|
|
150
|
+
kind: 'raw',
|
|
151
|
+
source: 'patches/ttsc@0.19.3.patch',
|
|
152
|
+
target: 'patches/ttsc@0.19.3.patch',
|
|
153
|
+
},
|
|
148
154
|
{
|
|
149
155
|
kind: 'generated',
|
|
150
156
|
source: 'ci-workflow',
|
|
@@ -156,6 +162,11 @@ const managedFiles = [
|
|
|
156
162
|
target: '.github/workflows/publish.yml',
|
|
157
163
|
releasePackagesOnly: true,
|
|
158
164
|
},
|
|
165
|
+
{
|
|
166
|
+
kind: 'template',
|
|
167
|
+
source: 'github/workflows/managed-files.yml',
|
|
168
|
+
target: '.github/workflows/managed-files.yml',
|
|
169
|
+
},
|
|
159
170
|
{
|
|
160
171
|
kind: 'template',
|
|
161
172
|
source: 'github/actions/cache-nix-devenv/action.yml',
|
|
@@ -176,6 +187,11 @@ const managedFiles = [
|
|
|
176
187
|
source: 'github/actions/cache-node-modules/action.yml',
|
|
177
188
|
target: '.github/actions/cache-node-modules/action.yml',
|
|
178
189
|
},
|
|
190
|
+
{
|
|
191
|
+
kind: 'template',
|
|
192
|
+
source: 'github/actions/cache-ttsc-plugins/action.yml',
|
|
193
|
+
target: '.github/actions/cache-ttsc-plugins/action.yml',
|
|
194
|
+
},
|
|
179
195
|
{
|
|
180
196
|
kind: 'template',
|
|
181
197
|
source: 'github/actions/cache-nx/action.yml',
|
|
@@ -283,8 +299,8 @@ function readResolvedNxTargetNames(root) {
|
|
|
283
299
|
encoding: 'utf8',
|
|
284
300
|
stdio: ['ignore', 'pipe', 'inherit'],
|
|
285
301
|
});
|
|
286
|
-
const projects =
|
|
287
|
-
if (!
|
|
302
|
+
const projects = parseStringArrayText(output);
|
|
303
|
+
if (!projects) {
|
|
288
304
|
return [];
|
|
289
305
|
}
|
|
290
306
|
const targetNames = new Set();
|
|
@@ -294,8 +310,8 @@ function readResolvedNxTargetNames(root) {
|
|
|
294
310
|
encoding: 'utf8',
|
|
295
311
|
stdio: ['ignore', 'pipe', 'inherit'],
|
|
296
312
|
});
|
|
297
|
-
const projectJson =
|
|
298
|
-
const targets =
|
|
313
|
+
const projectJson = parseNxProjectJsonText(projectOutput);
|
|
314
|
+
const targets = projectJson?.targets;
|
|
299
315
|
if (targets) {
|
|
300
316
|
for (const targetName of Object.keys(targets)) {
|
|
301
317
|
targetNames.add(targetName);
|
|
@@ -316,8 +332,8 @@ function getDeployTargetInfo(root, configuration) {
|
|
|
316
332
|
encoding: 'utf8',
|
|
317
333
|
stdio: ['ignore', 'pipe', 'inherit'],
|
|
318
334
|
});
|
|
319
|
-
const projects =
|
|
320
|
-
if (!
|
|
335
|
+
const projects = parseStringArrayText(output);
|
|
336
|
+
if (!projects) {
|
|
321
337
|
return { exists: false };
|
|
322
338
|
}
|
|
323
339
|
let exists = false;
|
|
@@ -338,41 +354,23 @@ function nxDeployTarget(root, project, configuration) {
|
|
|
338
354
|
encoding: 'utf8',
|
|
339
355
|
stdio: ['ignore', 'pipe', 'inherit'],
|
|
340
356
|
});
|
|
341
|
-
const
|
|
342
|
-
const
|
|
343
|
-
const
|
|
344
|
-
const deploy = recordValue(targets?.deploy);
|
|
345
|
-
const configurations = recordValue(deploy?.configurations);
|
|
346
|
-
const config = recordValue(configurations?.[configuration]);
|
|
357
|
+
const projectJson = parseNxProjectJsonText(output);
|
|
358
|
+
const deploy = projectJson?.targets?.deploy;
|
|
359
|
+
const config = deploy?.configurations?.[configuration];
|
|
347
360
|
if (!config) {
|
|
348
361
|
return { exists: false };
|
|
349
362
|
}
|
|
350
|
-
const
|
|
363
|
+
const commandValue = config.command ?? config.options?.command ?? deploy?.options?.command;
|
|
364
|
+
const command = typeof commandValue === 'string' ? commandValue : '';
|
|
351
365
|
return { exists: true, provider: command.includes('wrangler ') ? 'cloudflare' : undefined };
|
|
352
366
|
}
|
|
353
|
-
function deployCommand(deploy, config) {
|
|
354
|
-
const command = stringValue(config.command) ?? stringValue(recordValue(config.options)?.command);
|
|
355
|
-
return command ?? stringValue(recordValue(deploy?.options)?.command) ?? '';
|
|
356
|
-
}
|
|
357
|
-
function stringValue(value) {
|
|
358
|
-
return typeof value === 'string' ? value : undefined;
|
|
359
|
-
}
|
|
360
367
|
function getCiPushBranches(packageJson) {
|
|
361
368
|
const configured = readCiPushBranches(packageJson);
|
|
362
369
|
return configured.length > 0 ? configured : ['main'];
|
|
363
370
|
}
|
|
364
371
|
function readCiPushBranches(packageJson) {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
const github = recordValue(smoo?.github);
|
|
368
|
-
const branches = Array.isArray(github?.pushBranches) ? github.pushBranches : [];
|
|
369
|
-
return branches.filter((branch) => typeof branch === 'string' && branch.length > 0);
|
|
370
|
-
}
|
|
371
|
-
function recordValue(value) {
|
|
372
|
-
return isRecord(value) ? value : undefined;
|
|
373
|
-
}
|
|
374
|
-
function isRecord(value) {
|
|
375
|
-
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
372
|
+
const branches = packageJson?.smoo?.github?.pushBranches ?? [];
|
|
373
|
+
return branches.filter((branch) => branch.length > 0);
|
|
376
374
|
}
|
|
377
375
|
function renderYamlFlowList(values) {
|
|
378
376
|
return JSON.stringify(values);
|
|
@@ -395,3 +393,30 @@ export function validateManagedFiles(root) {
|
|
|
395
393
|
}
|
|
396
394
|
return failures;
|
|
397
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* Non-blocking drift report: prints the per-file table and surfaces drift as
|
|
398
|
+
* GitHub Actions warning annotations (plain stderr elsewhere) without failing
|
|
399
|
+
* the run. Managed-file drift is derived state with its own remediation flow
|
|
400
|
+
* (the persistent managed-files PR); only `monorepo check` without --warn and
|
|
401
|
+
* PR-scoped gates treat it as an error.
|
|
402
|
+
*
|
|
403
|
+
* Under GitHub Actions the drifted-file count is published as the step output
|
|
404
|
+
* `drifted`, so downstream steps gate declaratively instead of parsing logs.
|
|
405
|
+
*/
|
|
406
|
+
export function warnOnManagedFileDrift(root) {
|
|
407
|
+
const results = applyManagedFiles(root, 'check');
|
|
408
|
+
printResults(results);
|
|
409
|
+
const drifted = results.filter((result) => result.action === 'drifted');
|
|
410
|
+
if (process.env.GITHUB_OUTPUT) {
|
|
411
|
+
appendFileSync(process.env.GITHUB_OUTPUT, `drifted=${drifted.length}\n`);
|
|
412
|
+
}
|
|
413
|
+
if (drifted.length === 0) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
if (process.env.GITHUB_ACTIONS === 'true') {
|
|
417
|
+
for (const result of drifted) {
|
|
418
|
+
console.log(`::warning title=Managed file drift::${result.target} drifted from the @smoothbricks/cli template; run 'smoo monorepo update'`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
console.error(`${drifted.length} managed monorepo file(s) drifted (non-blocking). Run: smoo monorepo update`);
|
|
422
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-policy.d.ts","sourceRoot":"","sources":["../../src/monorepo/package-policy.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAGL,2BAA2B,EAC3B,uBAAuB,EACxB,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"package-policy.d.ts","sourceRoot":"","sources":["../../src/monorepo/package-policy.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC5B,MAAM,+CAA+C,CAAC;AACvD,OAAO,EAGL,2BAA2B,EAC3B,uBAAuB,EACxB,MAAM,+CAA+C,CAAC;AAoCvD,YAAY,EAAE,0BAA0B,IAAI,iCAAiC,EAAE,sBAAsB,EAAE,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,CAAC;AAYhE,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAuB1D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CA0C7D;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,IAAI,CAwB7G;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMzD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoB7D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAczD;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsC9D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwB3D;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcvD;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgElE;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAkC5G"}
|
|
@@ -4,7 +4,7 @@ import { applyPackageTargetPolicy, checkPackageTargetPolicy, } from '@smoothbric
|
|
|
4
4
|
import { applyReleaseConfigPolicy, checkReleaseConfigPolicy, SMOO_NX_RELEASE_TAG_PATTERN, SMOO_NX_VERSION_ACTIONS, } from '@smoothbricks/nx-plugin/release-config-policy';
|
|
5
5
|
import { applyTypecheckTestPolicy, checkTypecheckTestPolicy } from '@smoothbricks/nx-plugin/typecheck-test-policy';
|
|
6
6
|
import { applyWorkspaceConfigPolicy, checkWorkspaceConfigPolicy, } from '@smoothbricks/nx-plugin/workspace-config-policy';
|
|
7
|
-
import {
|
|
7
|
+
import { ensureNx, ensurePublishConfig, ensureRepositoryObject, ensureScripts, readJsonObject, requiredJsonObject, setMissingPackageStringField, setMissingRepositoryField, setNxName, setPublishAccess, setRepositoryField, setStringProperty, writeJsonObject, } from '../lib/json.js';
|
|
8
8
|
import { getWorkspacePackageManifests, getWorkspacePackages, listPackageJsonRecords, listPublicPackages, packageRepositoryInfo, repositoryInfo, sameRepositoryAfterNormalization, workspaceDependencyFields, } from '../lib/workspace.js';
|
|
9
9
|
export { SMOO_NX_RELEASE_TAG_PATTERN, SMOO_NX_VERSION_ACTIONS };
|
|
10
10
|
const extraCommitScopes = ['release'];
|
|
@@ -27,12 +27,12 @@ export function applyRootScriptDefaults(root) {
|
|
|
27
27
|
if (!rootPackage) {
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
|
-
const scripts =
|
|
30
|
+
const scripts = ensureScripts(rootPackage);
|
|
31
31
|
let changed = false;
|
|
32
32
|
for (const [name, command] of Object.entries(rootScriptPolicy)) {
|
|
33
33
|
changed = setStringProperty(scripts, name, command) || changed;
|
|
34
34
|
}
|
|
35
|
-
const nx =
|
|
35
|
+
const nx = ensureNx(rootPackage);
|
|
36
36
|
if (!Array.isArray(nx.includedScripts) || nx.includedScripts.length !== 0) {
|
|
37
37
|
nx.includedScripts = [];
|
|
38
38
|
changed = true;
|
|
@@ -56,7 +56,7 @@ export function applyNxPluginDefaults(root) {
|
|
|
56
56
|
}
|
|
57
57
|
export function applyPublicPackageDefaults(root) {
|
|
58
58
|
const rootPackage = requiredJsonObject(join(root, 'package.json'));
|
|
59
|
-
const rootLicense =
|
|
59
|
+
const rootLicense = rootPackage.license;
|
|
60
60
|
const rootRepository = repositoryInfo(rootPackage);
|
|
61
61
|
for (const pkg of listPublicPackages(root)) {
|
|
62
62
|
let changed = false;
|
|
@@ -66,17 +66,19 @@ export function applyPublicPackageDefaults(root) {
|
|
|
66
66
|
existingRepository.url === rootRepository.url &&
|
|
67
67
|
rootLicense &&
|
|
68
68
|
rootLicense !== 'UNLICENSED') {
|
|
69
|
-
changed =
|
|
69
|
+
changed = setMissingPackageStringField(pkg.json, 'license', rootLicense) || changed;
|
|
70
70
|
}
|
|
71
|
-
const publishConfig =
|
|
72
|
-
changed =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
const publishConfig = ensurePublishConfig(pkg.json);
|
|
72
|
+
changed = setPublishAccess(publishConfig, 'public') || changed;
|
|
73
|
+
if (typeof pkg.json.repository !== 'string') {
|
|
74
|
+
const repository = ensureRepositoryObject(pkg.json);
|
|
75
|
+
changed =
|
|
76
|
+
setRepositoryField(repository, 'type', existingRepository?.type ?? rootRepository?.type ?? 'git') || changed;
|
|
77
|
+
if (existingRepository) {
|
|
78
|
+
changed = setMissingRepositoryField(repository, 'url', existingRepository.url) || changed;
|
|
79
|
+
}
|
|
80
|
+
changed = setRepositoryField(repository, 'directory', pkg.path.replaceAll('\\', '/')) || changed;
|
|
78
81
|
}
|
|
79
|
-
changed = setStringProperty(repository, 'directory', pkg.path.replaceAll('\\', '/')) || changed;
|
|
80
82
|
changed = normalizeExportConditionOrder(pkg.json.exports) || changed;
|
|
81
83
|
if (hasDevelopmentSourceExport(pkg.json.exports)) {
|
|
82
84
|
changed = addFileEntry(pkg.json, 'src') || changed;
|
|
@@ -128,7 +130,7 @@ export function applyNxReleaseDefaults(root) {
|
|
|
128
130
|
}
|
|
129
131
|
export function applyNxProjectNameDefaults(root) {
|
|
130
132
|
const rootPackage = requiredJsonObject(join(root, 'package.json'));
|
|
131
|
-
const rootName =
|
|
133
|
+
const rootName = rootPackage.name;
|
|
132
134
|
if (!rootName) {
|
|
133
135
|
return;
|
|
134
136
|
}
|
|
@@ -137,8 +139,8 @@ export function applyNxProjectNameDefaults(root) {
|
|
|
137
139
|
if (!suggestedName) {
|
|
138
140
|
continue;
|
|
139
141
|
}
|
|
140
|
-
const nx =
|
|
141
|
-
const changed =
|
|
142
|
+
const nx = ensureNx(pkg.json);
|
|
143
|
+
const changed = setNxName(nx, suggestedName);
|
|
142
144
|
if (changed) {
|
|
143
145
|
writeJsonObject(pkg.packageJsonPath, pkg.json);
|
|
144
146
|
console.log(`updated ${pkg.path}/package.json nx.name`);
|
|
@@ -153,11 +155,10 @@ export function listValidCommitScopes(root) {
|
|
|
153
155
|
}
|
|
154
156
|
export function listNxProjectNames(root) {
|
|
155
157
|
const rootPackage = readJsonObject(join(root, 'package.json'));
|
|
156
|
-
const rootName = rootPackage
|
|
158
|
+
const rootName = rootPackage?.name ?? null;
|
|
157
159
|
const names = [];
|
|
158
160
|
for (const pkg of getWorkspacePackageManifests(root)) {
|
|
159
|
-
const
|
|
160
|
-
const configuredName = nx ? stringProperty(nx, 'name') : null;
|
|
161
|
+
const configuredName = pkg.json.nx?.name;
|
|
161
162
|
const suggestedName = rootName ? suggestNxProjectName(rootName, pkg.name) : null;
|
|
162
163
|
if (configuredName) {
|
|
163
164
|
names.push(configuredName);
|
|
@@ -175,11 +176,11 @@ export function validateRootPackagePolicy(root) {
|
|
|
175
176
|
return 1;
|
|
176
177
|
}
|
|
177
178
|
let failures = 0;
|
|
178
|
-
if (!
|
|
179
|
+
if (!rootPackage.name) {
|
|
179
180
|
console.error('package.json must define name');
|
|
180
181
|
failures++;
|
|
181
182
|
}
|
|
182
|
-
if (!
|
|
183
|
+
if (!rootPackage.license) {
|
|
183
184
|
console.error('package.json must define repo-wide license');
|
|
184
185
|
failures++;
|
|
185
186
|
}
|
|
@@ -189,19 +190,19 @@ export function validateRootPackagePolicy(root) {
|
|
|
189
190
|
}
|
|
190
191
|
failures += validateRootScripts(rootPackage);
|
|
191
192
|
failures += validateRootNxScriptInference(rootPackage);
|
|
192
|
-
const packageManager =
|
|
193
|
+
const packageManager = rootPackage.packageManager;
|
|
193
194
|
if (!packageManager?.startsWith('bun@')) {
|
|
194
195
|
console.error('package.json packageManager must use bun@<version>');
|
|
195
196
|
failures++;
|
|
196
197
|
}
|
|
197
198
|
const bunVersion = packageManager?.startsWith('bun@') ? packageManager.slice('bun@'.length) : null;
|
|
198
|
-
const devDependencies =
|
|
199
|
+
const devDependencies = rootPackage.devDependencies;
|
|
199
200
|
if (!bunVersion || !devDependencies || devDependencies['@types/bun'] !== bunVersion) {
|
|
200
201
|
console.error('package.json devDependencies.@types/bun must match packageManager bun version');
|
|
201
202
|
failures++;
|
|
202
203
|
}
|
|
203
|
-
const engines =
|
|
204
|
-
if (!engines
|
|
204
|
+
const engines = rootPackage.engines;
|
|
205
|
+
if (!engines?.node) {
|
|
205
206
|
console.error('package.json engines.node must be defined');
|
|
206
207
|
failures++;
|
|
207
208
|
}
|
|
@@ -221,7 +222,7 @@ export function validateNxReleaseConfig(root) {
|
|
|
221
222
|
}
|
|
222
223
|
export function validateNxProjectNames(root) {
|
|
223
224
|
const rootPackage = readJsonObject(join(root, 'package.json'));
|
|
224
|
-
const rootName = rootPackage
|
|
225
|
+
const rootName = rootPackage?.name ?? null;
|
|
225
226
|
if (!rootName) {
|
|
226
227
|
return 0;
|
|
227
228
|
}
|
|
@@ -231,8 +232,7 @@ export function validateNxProjectNames(root) {
|
|
|
231
232
|
if (!suggestedName) {
|
|
232
233
|
continue;
|
|
233
234
|
}
|
|
234
|
-
const
|
|
235
|
-
const configuredName = nx ? stringProperty(nx, 'name') : null;
|
|
235
|
+
const configuredName = pkg.json.nx?.name ?? null;
|
|
236
236
|
if (configuredName !== suggestedName) {
|
|
237
237
|
console.error(`${pkg.path}: package.json nx.name must be "${suggestedName}" so fix(${suggestedName}): maps to this project`);
|
|
238
238
|
failures++;
|
|
@@ -267,16 +267,18 @@ export function validatePublicPackageMetadata(root) {
|
|
|
267
267
|
console.error(`${pkg.path}: npm:public package must not be private`);
|
|
268
268
|
failures++;
|
|
269
269
|
}
|
|
270
|
-
if (!
|
|
270
|
+
if (!pkg.json.license) {
|
|
271
271
|
console.error(`${pkg.path}: public package must define license`);
|
|
272
272
|
failures++;
|
|
273
273
|
}
|
|
274
|
-
const publishConfig =
|
|
275
|
-
if (
|
|
274
|
+
const publishConfig = pkg.json.publishConfig;
|
|
275
|
+
if (publishConfig?.access !== 'public') {
|
|
276
276
|
console.error(`${pkg.path}: public package must define publishConfig.access = public`);
|
|
277
277
|
failures++;
|
|
278
278
|
}
|
|
279
|
-
const repository =
|
|
279
|
+
const repository = pkg.json.repository !== null && pkg.json.repository !== undefined && typeof pkg.json.repository !== 'string'
|
|
280
|
+
? pkg.json.repository
|
|
281
|
+
: null;
|
|
280
282
|
const packageRepository = packageRepositoryInfo(pkg);
|
|
281
283
|
if (!packageRepository) {
|
|
282
284
|
console.error(`${pkg.path}: public package must define repository.url`);
|
|
@@ -290,11 +292,11 @@ export function validatePublicPackageMetadata(root) {
|
|
|
290
292
|
`Use ${rootRepository.url}`);
|
|
291
293
|
failures++;
|
|
292
294
|
}
|
|
293
|
-
if (!repository
|
|
295
|
+
if (!repository?.type) {
|
|
294
296
|
console.error(`${pkg.path}: public package must define repository.type`);
|
|
295
297
|
failures++;
|
|
296
298
|
}
|
|
297
|
-
if (!repository ||
|
|
299
|
+
if (!repository || repository.directory !== pkg.path.replaceAll('\\', '/')) {
|
|
298
300
|
console.error(`${pkg.path}: public package repository.directory must be ${pkg.path.replaceAll('\\', '/')}`);
|
|
299
301
|
failures++;
|
|
300
302
|
}
|
|
@@ -302,11 +304,13 @@ export function validatePublicPackageMetadata(root) {
|
|
|
302
304
|
console.error(`${pkg.path}: public package must define files`);
|
|
303
305
|
failures++;
|
|
304
306
|
}
|
|
305
|
-
|
|
307
|
+
const hasBin = typeof pkg.json.bin === 'string' ||
|
|
308
|
+
(pkg.json.bin !== null && pkg.json.bin !== undefined && typeof pkg.json.bin === 'object');
|
|
309
|
+
if (!isPackageExportMap(pkg.json.exports) && !hasBin) {
|
|
306
310
|
console.error(`${pkg.path}: public package must define exports or bin`);
|
|
307
311
|
failures++;
|
|
308
312
|
}
|
|
309
|
-
if (
|
|
313
|
+
if (typeof pkg.json.types !== 'string' && !hasBin) {
|
|
310
314
|
console.error(`${pkg.path}: public library package must define types`);
|
|
311
315
|
failures++;
|
|
312
316
|
}
|
|
@@ -319,7 +323,7 @@ export function validateWorkspaceDependencies(root, options = {}) {
|
|
|
319
323
|
const workspaceNames = new Set(getWorkspacePackages(root).map((pkg) => pkg.name));
|
|
320
324
|
for (const pkg of listPackageJsonRecords(root)) {
|
|
321
325
|
for (const field of workspaceDependencyFields) {
|
|
322
|
-
const dependencies =
|
|
326
|
+
const dependencies = pkg.json[field];
|
|
323
327
|
if (!dependencies) {
|
|
324
328
|
continue;
|
|
325
329
|
}
|
|
@@ -379,7 +383,7 @@ function validateCiSkipTags(root, options) {
|
|
|
379
383
|
function fixWorkspaceDependencyRanges(pkg, workspaceNames) {
|
|
380
384
|
let changed = false;
|
|
381
385
|
for (const field of workspaceDependencyFields) {
|
|
382
|
-
const dependencies =
|
|
386
|
+
const dependencies = pkg[field];
|
|
383
387
|
if (!dependencies) {
|
|
384
388
|
continue;
|
|
385
389
|
}
|
|
@@ -393,7 +397,7 @@ function fixWorkspaceDependencyRanges(pkg, workspaceNames) {
|
|
|
393
397
|
return changed;
|
|
394
398
|
}
|
|
395
399
|
function validateRootScripts(rootPackage) {
|
|
396
|
-
const scripts =
|
|
400
|
+
const scripts = rootPackage.scripts;
|
|
397
401
|
let failures = 0;
|
|
398
402
|
for (const [name, command] of Object.entries(rootScriptPolicy)) {
|
|
399
403
|
if (scripts?.[name] !== command) {
|
|
@@ -408,8 +412,8 @@ function validateRootScripts(rootPackage) {
|
|
|
408
412
|
return failures;
|
|
409
413
|
}
|
|
410
414
|
function validateRootNxScriptInference(rootPackage) {
|
|
411
|
-
const
|
|
412
|
-
if (
|
|
415
|
+
const includedScripts = rootPackage.nx?.includedScripts;
|
|
416
|
+
if (Array.isArray(includedScripts) && includedScripts.length === 0) {
|
|
413
417
|
return 0;
|
|
414
418
|
}
|
|
415
419
|
console.error('package.json nx.includedScripts must be [] so root scripts do not become recursive Nx targets.');
|
|
@@ -431,7 +435,7 @@ function unscopedPackageName(packageName) {
|
|
|
431
435
|
}
|
|
432
436
|
function recordKeysAreSorted(record) {
|
|
433
437
|
const keys = Object.keys(record);
|
|
434
|
-
return keys.every((key, index) => index === 0 || keys[index - 1] <= key);
|
|
438
|
+
return keys.every((key, index) => index === 0 || (keys[index - 1] ?? '') <= key);
|
|
435
439
|
}
|
|
436
440
|
function sortRecordInPlace(record) {
|
|
437
441
|
if (recordKeysAreSorted(record)) {
|
|
@@ -446,8 +450,11 @@ function sortRecordInPlace(record) {
|
|
|
446
450
|
}
|
|
447
451
|
return true;
|
|
448
452
|
}
|
|
453
|
+
function isPackageExportMap(value) {
|
|
454
|
+
return value !== null && value !== undefined && typeof value === 'object';
|
|
455
|
+
}
|
|
449
456
|
function normalizeExportConditionOrder(value) {
|
|
450
|
-
if (!
|
|
457
|
+
if (!isPackageExportMap(value)) {
|
|
451
458
|
return false;
|
|
452
459
|
}
|
|
453
460
|
let changed = false;
|
|
@@ -476,7 +483,7 @@ function normalizeExportConditionOrder(value) {
|
|
|
476
483
|
return true;
|
|
477
484
|
}
|
|
478
485
|
function hasDevelopmentSourceExport(value) {
|
|
479
|
-
if (!
|
|
486
|
+
if (!isPackageExportMap(value)) {
|
|
480
487
|
return false;
|
|
481
488
|
}
|
|
482
489
|
for (const [key, child] of Object.entries(value)) {
|
|
@@ -494,7 +501,7 @@ function addFileEntry(pkg, entry) {
|
|
|
494
501
|
if (!Array.isArray(files) || files.includes(entry)) {
|
|
495
502
|
return false;
|
|
496
503
|
}
|
|
497
|
-
const firstNegated = files.findIndex((file) =>
|
|
504
|
+
const firstNegated = files.findIndex((file) => file.startsWith('!'));
|
|
498
505
|
if (firstNegated === -1) {
|
|
499
506
|
files.push(entry);
|
|
500
507
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { type PackageJson } from '../lib/json.js';
|
|
1
2
|
import type { PackageInfo } from '../lib/workspace.js';
|
|
2
|
-
export declare function readPackedPackageJson(root: string, tarball: string, packageName: string): Promise<
|
|
3
|
-
export declare function validatePackedWorkspaceDependencies(root: string, sourcePackage: PackageInfo, packedPackage:
|
|
3
|
+
export declare function readPackedPackageJson(root: string, tarball: string, packageName: string): Promise<PackageJson>;
|
|
4
|
+
export declare function validatePackedWorkspaceDependencies(root: string, sourcePackage: PackageInfo, packedPackage: PackageJson, options?: {
|
|
5
|
+
mode?: 'install' | 'publish';
|
|
6
|
+
}): string[];
|
|
4
7
|
//# sourceMappingURL=packed-manifest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packed-manifest.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"packed-manifest.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAwB,MAAM,gBAAgB,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAUpH;AAED,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,WAAW,EAC1B,aAAa,EAAE,WAAW,EAC1B,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CAAO,GAC7C,MAAM,EAAE,CAyCV"}
|
|
@@ -1,32 +1,31 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
1
|
import { $ } from 'bun';
|
|
3
|
-
import {
|
|
2
|
+
import { parsePackageJsonText } from '../lib/json.js';
|
|
4
3
|
import { decode } from '../lib/run.js';
|
|
5
4
|
import { getWorkspacePackages, workspaceDependencyFields } from '../lib/workspace.js';
|
|
5
|
+
import { publishPackDependencyVersion } from './lockfile.js';
|
|
6
6
|
export async function readPackedPackageJson(root, tarball, packageName) {
|
|
7
7
|
const result = await $ `tar -xOf ${tarball} package/package.json`.cwd(root).quiet().nothrow();
|
|
8
8
|
if (result.exitCode !== 0) {
|
|
9
9
|
throw new Error(`${packageName}: unable to inspect packed package.json.`);
|
|
10
10
|
}
|
|
11
|
-
const parsed =
|
|
12
|
-
if (!
|
|
13
|
-
throw new Error(`${packageName}: packed package.json is
|
|
11
|
+
const parsed = parsePackageJsonText(decode(result.stdout));
|
|
12
|
+
if (!parsed) {
|
|
13
|
+
throw new Error(`${packageName}: packed package.json is invalid.`);
|
|
14
14
|
}
|
|
15
15
|
return parsed;
|
|
16
16
|
}
|
|
17
|
-
export function validatePackedWorkspaceDependencies(root, sourcePackage, packedPackage) {
|
|
17
|
+
export function validatePackedWorkspaceDependencies(root, sourcePackage, packedPackage, options = {}) {
|
|
18
|
+
const mode = options.mode ?? 'publish';
|
|
18
19
|
const workspacePackages = getWorkspacePackages(root);
|
|
19
|
-
const workspaceVersions = new Map(workspacePackages.map((pkg) => [pkg.name, pkg.version]));
|
|
20
|
-
const projectNameByPackage = new Map(workspacePackages.map((pkg) => [pkg.name, pkg.projectName]));
|
|
21
20
|
const failures = [];
|
|
22
21
|
for (const field of workspaceDependencyFields) {
|
|
23
|
-
const sourceDependencies =
|
|
24
|
-
const packedDependencies =
|
|
22
|
+
const sourceDependencies = sourcePackage.json[field];
|
|
23
|
+
const packedDependencies = packedPackage[field];
|
|
25
24
|
if (!sourceDependencies && !packedDependencies) {
|
|
26
25
|
continue;
|
|
27
26
|
}
|
|
28
27
|
for (const [name, range] of Object.entries(packedDependencies ?? {})) {
|
|
29
|
-
if (
|
|
28
|
+
if (range.startsWith('workspace:')) {
|
|
30
29
|
failures.push(`${sourcePackage.path}: packed ${field}.${name} must not contain ${range}`);
|
|
31
30
|
}
|
|
32
31
|
}
|
|
@@ -34,51 +33,21 @@ export function validatePackedWorkspaceDependencies(root, sourcePackage, packedP
|
|
|
34
33
|
continue;
|
|
35
34
|
}
|
|
36
35
|
for (const [name, sourceRange] of Object.entries(sourceDependencies)) {
|
|
37
|
-
const
|
|
38
|
-
if (!
|
|
36
|
+
const dep = workspacePackages.find((pkg) => pkg.name === name);
|
|
37
|
+
if (!dep) {
|
|
39
38
|
continue;
|
|
40
39
|
}
|
|
41
40
|
const packedRange = packedDependencies?.[name];
|
|
42
41
|
if (sourceRange !== 'workspace:*') {
|
|
43
42
|
failures.push(`${sourcePackage.path}: source ${field}.${name} must use workspace:*`);
|
|
44
43
|
}
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
const projectName = projectNameByPackage.get(name);
|
|
49
|
-
const expectedVersion = workspaceVersion.includes('-') && projectName
|
|
50
|
-
? (latestStableTagVersion(root, projectName) ?? workspaceVersion)
|
|
51
|
-
: workspaceVersion;
|
|
44
|
+
// install: what day-to-day pack embeds (package.json / lockfile aligned)
|
|
45
|
+
// publish: what pre-publish sync embeds (unpublished -next → last stable tag)
|
|
46
|
+
const expectedVersion = mode === 'publish' ? publishPackDependencyVersion(root, dep.projectName, dep.version) : dep.version;
|
|
52
47
|
if (packedRange !== expectedVersion) {
|
|
53
|
-
failures.push(`${sourcePackage.path}: packed ${field}.${name} must be ${expectedVersion}, got ${
|
|
48
|
+
failures.push(`${sourcePackage.path}: packed ${field}.${name} must be ${expectedVersion}, got ${packedRange ?? '<missing>'}`);
|
|
54
49
|
}
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
52
|
return failures;
|
|
58
53
|
}
|
|
59
|
-
function formatRange(value) {
|
|
60
|
-
return typeof value === 'string' ? value : '<missing>';
|
|
61
|
-
}
|
|
62
|
-
function latestStableTagVersion(root, projectName) {
|
|
63
|
-
try {
|
|
64
|
-
const output = execSync(`git tag --list '${projectName}@*' --sort=-v:refname`, {
|
|
65
|
-
cwd: root,
|
|
66
|
-
encoding: 'utf8',
|
|
67
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
68
|
-
});
|
|
69
|
-
const prefix = `${projectName}@`;
|
|
70
|
-
for (const line of output.split('\n')) {
|
|
71
|
-
const tag = line.trim();
|
|
72
|
-
if (!tag.startsWith(prefix))
|
|
73
|
-
continue;
|
|
74
|
-
const version = tag.slice(prefix.length);
|
|
75
|
-
if (version && !version.includes('-')) {
|
|
76
|
-
return version;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packed-package.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-package.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"packed-package.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-package.ts"],"names":[],"mappings":"AAcA,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMhF;AAED,wBAAsB,kCAAkC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtF;AAED,wBAAsB,mCAAmC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMvF;AAED,wBAAsB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpF"}
|