@vzn/vx-migrate 0.0.642 → 0.0.643
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 +3 -3
- package/package.json +2 -2
- package/src/migrate-nx.ts +8 -6
- package/src/nx/index.ts +12 -11
- package/src/turbo/index.ts +1 -2
- package/src/workspace-plugins.ts +9 -4
package/README.md
CHANGED
|
@@ -76,7 +76,7 @@ Rules:
|
|
|
76
76
|
- A task's `tags` (Turbo main, after 2.11.5) map to nothing: Turbo keeps them out of the hash and the run.
|
|
77
77
|
- `envMode: "loose"` (top-level or in `global`, or `TURBO_ENV_MODE=loose`, which wins) is a note: Turbo hands every task the whole environment, vx only the declared names.
|
|
78
78
|
- The workspace keys vx has a home for, top level or in `global`, fill what `.vx/workspace.ts` leaves unset: `run.concurrency` (`"10"`, `"50%"` of the cores) → `run.concurrency`; `cacheMaxSize` / `cacheMaxAge` (`"0"` is off; weeks become days, a bare number days; a size in Turbo's grammar, `7.5GB` or bare bytes, restated whole: `7680MB`) → `cache.retention.maxSize` / `.olderThan`. `TURBO_CONCURRENCY`, `TURBO_CACHE_MAX_SIZE` and `TURBO_CACHE_MAX_AGE` win over turbo.json, as under Turbo; a set one decides, its `0` included.
|
|
79
|
-
- `TURBO_SCM_BASE`, the base `turbo run --affected` compares with, is
|
|
79
|
+
- `TURBO_SCM_BASE`, the base `turbo run --affected` compares with, is the run's base commit (`setBranch({ base })`): a bare `vx run build --affected` compares with the same ref. With it unset on GitHub Actions (`GITHUB_ACTIONS`), Turbo's own base applies: a pull request's `GITHUB_BASE_REF`, else the push event's `before` from `GITHUB_EVENT_PATH`.
|
|
80
80
|
- Turbo hashes each package's `microfrontends.json` (or `.jsonc`) into every task, or the one file `VC_MICROFRONTENDS_CONFIG_FILE_NAME` names; so does `turbo()`.
|
|
81
81
|
- Turbo 2.11's `global` block (`futureFlags.globalConfiguration`) is read as the `globalDependencies`, `globalEnv` and `globalPassThroughEnv` it replaces.
|
|
82
82
|
- An unknown Turbo key is a todo naming it; `extends` is accepted and ignored (the overlay order above is what it means).
|
|
@@ -169,7 +169,7 @@ Two cached tasks on one workspace path cannot both keep their cache, and the fir
|
|
|
169
169
|
|
|
170
170
|
### nx.json `defaultBase`
|
|
171
171
|
|
|
172
|
-
`NX_BASE
|
|
172
|
+
`NX_BASE` is the run's base commit (`setBranch({ base })`), and `defaultBase` (Nx 19's `affected.defaultBase` before it, an `origin/` prefix dropped) is `baseBranch` when `.vx/workspace.ts` sets none: a bare `vx run test --affected` compares with the ref `nx affected` does.
|
|
173
173
|
|
|
174
174
|
### nx.json `maxCacheSize`
|
|
175
175
|
|
|
@@ -259,7 +259,7 @@ Reads the root pipeline (`tasks` in Turbo 2, `pipeline` in Turbo 1), per-package
|
|
|
259
259
|
|
|
260
260
|
### Nx
|
|
261
261
|
|
|
262
|
-
Reads the **resolved** project graph only (`.nx/workspace-data/project-graph.json` when exported, else the one the workspace's own `nx graph` exports into a temp file, as `nx()` does; with no `node_modules/.bin/nx`, as in a fresh clone, it stops and names the repo manager's install), through the same mapper `nx()` runs live, executors aside (below). Targets Nx plugins infer at runtime are frozen as the snapshot saw them. `nx:run-commands` is the one shell line `nx()` runs (see [`nx:run-commands`](#nxrun-commands) above: where, parallel or in order, forwarded arguments, `env`, `readyWhen`) — storybook's `compile` is `cd ../../.. && node ./scripts/build/build-package.ts --cwd code/lib/cli`; a plain `command` is that shorthand; `nx:run-script` is the package's script body with its `pre<name>` / `post<name>` hooks folded in (or `yarn run <name>` when the body calls yarn's `run` builtin; an empty script is the placeholder with a todo), `nx:noop` is a group task; Nx 15–16's `@nrwl/workspace:run-commands` and `run-script` (and their `@nx/workspace:` names) are the `nx:` executors they re-exported; **an executor target is its `nx-exec` line**, as `nx()` runs it: the migrator translates no executor, so Nx and `@vzn/vx-migrate` stay installed until each such line is rewritten as the command it runs (a server executor Nx knows, `@nx/js:node` or a dev server, is still a persistent task). The report also says what `.vx/workspace.ts` still holds, as the Turbo migration does: the `nx()` a keep adoption declared, which keeps reading nx.json, and a lockfile with no `@vzn/vx-lockfile` plugin, where Nx keyed each project on the npm packages it depends on. A written command that still runs Nx itself (a run-commands `nx run b:build`, `npx nx test b`, a script's `nx exec -- tsc`) carries a TODO: it works only while Nx is installed. An Nx project no workspace glob lists (an integrated repo's `project.json` library) gets a `package.json` (`name`, `private`) where it has none, and a note names the directories to add to `workspaces` (or `pnpm-workspace.yaml`), so the package manager installs it and a lockfile plugin names it; the migrator never edits the root manifest. A repo with no `package.json` at all (Nx's `nx init` outside JS: Nx pinned in `.nx/installation`, projects as `project.json`) is migrated too, natively only: the root is the directory holding `nx.json`, the graph is exported by `.nx/installation`'s `nx`, each config writes the project's Nx `name`, every edge is the explicit `project#target` Nx's graph draws (a `^` edge needs a lockfile plugin, which has no lockfile to read), and `.vx/workspace.ts` declares no plugin, so nothing is installed and core runs the configs alone; `--keep` refuses, as `nx()` would have no `package.json` to install into, and an executor target's `nx-exec` line is a note to rewrite as a command. A target with `configurations` writes one task per configuration (`build`, `build:ci`). A project's Nx `tags` are written as its `tags`. Named inputs expand from `nx.json` when readable. An output path is kept as written, a `!` one too (`{projectRoot}/dist` → `dist`, `{projectRoot}/bin/tool` → `bin/tool`; one naming an unset `{options.x}` is dropped, as Nx drops it; a dotted `{options.outputPath.base}` walks the options, as Nx does; an extglob is put in vx's grammar: Next's inferred `.next/!(cache)/**/*` is `.next/*/**/*` with `!.next/cache/**/*`, `@(js|map)` is `{js,map}`, and a form with no vx spelling is dropped with a TODO): vx reads a bare path as the file or the whole tree under it, so a directory and an extensionless binary both save and restore. nx.json's `parallel`, `defaultBase` and `maxCacheSize`, which `nx()` applies live, are each a field of the `.vx/workspace.ts` it writes (`run.concurrency`, `
|
|
262
|
+
Reads the **resolved** project graph only (`.nx/workspace-data/project-graph.json` when exported, else the one the workspace's own `nx graph` exports into a temp file, as `nx()` does; with no `node_modules/.bin/nx`, as in a fresh clone, it stops and names the repo manager's install), through the same mapper `nx()` runs live, executors aside (below). Targets Nx plugins infer at runtime are frozen as the snapshot saw them. `nx:run-commands` is the one shell line `nx()` runs (see [`nx:run-commands`](#nxrun-commands) above: where, parallel or in order, forwarded arguments, `env`, `readyWhen`) — storybook's `compile` is `cd ../../.. && node ./scripts/build/build-package.ts --cwd code/lib/cli`; a plain `command` is that shorthand; `nx:run-script` is the package's script body with its `pre<name>` / `post<name>` hooks folded in (or `yarn run <name>` when the body calls yarn's `run` builtin; an empty script is the placeholder with a todo), `nx:noop` is a group task; Nx 15–16's `@nrwl/workspace:run-commands` and `run-script` (and their `@nx/workspace:` names) are the `nx:` executors they re-exported; **an executor target is its `nx-exec` line**, as `nx()` runs it: the migrator translates no executor, so Nx and `@vzn/vx-migrate` stay installed until each such line is rewritten as the command it runs (a server executor Nx knows, `@nx/js:node` or a dev server, is still a persistent task). The report also says what `.vx/workspace.ts` still holds, as the Turbo migration does: the `nx()` a keep adoption declared, which keeps reading nx.json, and a lockfile with no `@vzn/vx-lockfile` plugin, where Nx keyed each project on the npm packages it depends on. A written command that still runs Nx itself (a run-commands `nx run b:build`, `npx nx test b`, a script's `nx exec -- tsc`) carries a TODO: it works only while Nx is installed. An Nx project no workspace glob lists (an integrated repo's `project.json` library) gets a `package.json` (`name`, `private`) where it has none, and a note names the directories to add to `workspaces` (or `pnpm-workspace.yaml`), so the package manager installs it and a lockfile plugin names it; the migrator never edits the root manifest. A repo with no `package.json` at all (Nx's `nx init` outside JS: Nx pinned in `.nx/installation`, projects as `project.json`) is migrated too, natively only: the root is the directory holding `nx.json`, the graph is exported by `.nx/installation`'s `nx`, each config writes the project's Nx `name`, every edge is the explicit `project#target` Nx's graph draws (a `^` edge needs a lockfile plugin, which has no lockfile to read), and `.vx/workspace.ts` declares no plugin, so nothing is installed and core runs the configs alone; `--keep` refuses, as `nx()` would have no `package.json` to install into, and an executor target's `nx-exec` line is a note to rewrite as a command. A target with `configurations` writes one task per configuration (`build`, `build:ci`). A project's Nx `tags` are written as its `tags`. Named inputs expand from `nx.json` when readable. An output path is kept as written, a `!` one too (`{projectRoot}/dist` → `dist`, `{projectRoot}/bin/tool` → `bin/tool`; one naming an unset `{options.x}` is dropped, as Nx drops it; a dotted `{options.outputPath.base}` walks the options, as Nx does; an extglob is put in vx's grammar: Next's inferred `.next/!(cache)/**/*` is `.next/*/**/*` with `!.next/cache/**/*`, `@(js|map)` is `{js,map}`, and a form with no vx spelling is dropped with a TODO): vx reads a bare path as the file or the whole tree under it, so a directory and an extensionless binary both save and restore. nx.json's `parallel`, `defaultBase` and `maxCacheSize`, which `nx()` applies live, are each a field of the `.vx/workspace.ts` it writes (`run.concurrency`, `baseBranch`, `cache.retention.maxSize`), read from nx.json alone, never the environment; beside a workspace file already there, or for a size vx cannot read (`1.5 GB`), each is a note naming the field to add. vx derives package edges from `package.json`; an Nx graph edge with no manifest path (`implicitDependencies`, a tsconfig path) becomes, for each `^target` of the dependant, an explicit `pkg#target` edge to what Nx's own walk reaches — each dependency that has the target, and through one that lacks it, its dependencies — so the order and the key are Nx's. The reverse too: where a project's manifest names a workspace package its Nx graph does not reach (an `implicitDependencies: ["!a"]` that breaks a manifest cycle), its `^target` becomes the explicit edges Nx draws, since vx's `^` would follow the manifest and bring the cycle back.
|
|
263
263
|
|
|
264
264
|
### Vite Task
|
|
265
265
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx-migrate",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.643",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Adopt @vzn/vx from Turborepo, Nx or package.json scripts: run the repo unchanged, migrate it to vx.config.ts, and keep your Turbo or Nx remote cache",
|
|
6
6
|
"keywords": [
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@vzn/vx": "^0.0.
|
|
43
|
+
"@vzn/vx": "^0.0.643"
|
|
44
44
|
},
|
|
45
45
|
"repository": {
|
|
46
46
|
"type": "git",
|
package/src/migrate-nx.ts
CHANGED
|
@@ -164,8 +164,8 @@ async function unlistedProjects(
|
|
|
164
164
|
|
|
165
165
|
/** A `.vx/workspace.ts` field nx.json's run settings call for. */
|
|
166
166
|
export interface NxWorkspaceField {
|
|
167
|
-
/** The setting's path: its group, then its field. */
|
|
168
|
-
readonly field: 'run.concurrency' | '
|
|
167
|
+
/** The setting's path: its group, then its field, or a top-level key. */
|
|
168
|
+
readonly field: 'run.concurrency' | 'baseBranch' | 'cache.retention'
|
|
169
169
|
/** The value as TypeScript source; undefined when vx cannot read it. */
|
|
170
170
|
readonly source: string | undefined
|
|
171
171
|
/** What to tell a user whose workspace file this run does not write. */
|
|
@@ -199,12 +199,14 @@ export function nxWorkspaceFields(json: Record<string, unknown> | undefined): Nx
|
|
|
199
199
|
note: `nx.json \`parallel: ${parallel}\`: add \`run: { concurrency: ${parallel} }\` to .vx/workspace.ts`,
|
|
200
200
|
})
|
|
201
201
|
const base = nx?.defaultBase ?? nx?.affected?.defaultBase
|
|
202
|
-
if (typeof base === 'string' && base.trim() !== '')
|
|
202
|
+
if (typeof base === 'string' && base.trim() !== '') {
|
|
203
|
+
const branch = base.trim().replace(/^origin\//, '')
|
|
203
204
|
out.push({
|
|
204
|
-
field: '
|
|
205
|
-
source: quoted(
|
|
206
|
-
note: `nx.json \`defaultBase\` ${JSON.stringify(base.trim())}: add \`
|
|
205
|
+
field: 'baseBranch',
|
|
206
|
+
source: quoted(branch),
|
|
207
|
+
note: `nx.json \`defaultBase\` ${JSON.stringify(base.trim())}: add \`baseBranch: ${JSON.stringify(branch)}\` to .vx/workspace.ts`,
|
|
207
208
|
})
|
|
209
|
+
}
|
|
208
210
|
const size = nxSizeText(nx?.maxCacheSize)
|
|
209
211
|
if (size !== undefined)
|
|
210
212
|
out.push({
|
package/src/nx/index.ts
CHANGED
|
@@ -148,9 +148,11 @@ export function nx(options: NxPluginOptions = {}): VxPlugin {
|
|
|
148
148
|
{
|
|
149
149
|
async config(workspace, ctx) {
|
|
150
150
|
const root = options.root ?? ctx.workspaceRoot
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
const nxBaseCommit = Bun.env['NX_BASE']?.trim()
|
|
152
|
+
if (nxBaseCommit) ctx.setBranch({ base: nxBaseCommit })
|
|
153
|
+
if (workspace.baseBranch === undefined) {
|
|
154
|
+
const branch = await nxDefaultBase(root)
|
|
155
|
+
if (branch !== undefined) workspace.baseBranch = branch
|
|
154
156
|
}
|
|
155
157
|
if (workspace.run?.concurrency === undefined) {
|
|
156
158
|
const parallel = await nxParallel(root)
|
|
@@ -278,19 +280,18 @@ async function nxParallel(root: string): Promise<number | undefined> {
|
|
|
278
280
|
}
|
|
279
281
|
|
|
280
282
|
/**
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
283
|
+
* nx.json's `defaultBase` (Nx 19's `affected.defaultBase` before it), the
|
|
284
|
+
* branch `nx affected` compares with. Read by nothing, a git-flow repo's
|
|
285
|
+
* `develop` was lost and a bare `vx run … --affected` diffed against
|
|
286
|
+
* origin/HEAD.
|
|
285
287
|
*/
|
|
286
|
-
async function
|
|
287
|
-
const env = Bun.env['NX_BASE']?.trim()
|
|
288
|
-
if (env) return env
|
|
288
|
+
async function nxDefaultBase(root: string): Promise<string | undefined> {
|
|
289
289
|
const json = (await readNxJson(root).catch(() => null))?.json as
|
|
290
290
|
| { defaultBase?: unknown; affected?: { defaultBase?: unknown } }
|
|
291
291
|
| undefined
|
|
292
292
|
const b = json?.defaultBase ?? json?.affected?.defaultBase
|
|
293
|
-
|
|
293
|
+
// `baseBranch` is the branch; vx compares with it on `origin`.
|
|
294
|
+
return typeof b === 'string' && b.trim() !== '' ? b.trim().replace(/^origin\//, '') : undefined
|
|
294
295
|
}
|
|
295
296
|
|
|
296
297
|
/**
|
package/src/turbo/index.ts
CHANGED
|
@@ -78,8 +78,7 @@ export function turbo(options: TurboPluginOptions = {}): VxPlugin {
|
|
|
78
78
|
const base =
|
|
79
79
|
Bun.env['TURBO_SCM_BASE']?.trim() ||
|
|
80
80
|
githubActionsBase(options.root ?? ctx.workspaceRoot, keys.remoteBaseFallback === true)
|
|
81
|
-
if (
|
|
82
|
-
workspace.run = { ...workspace.run, affectedBase: base }
|
|
81
|
+
if (base) ctx.setBranch({ base })
|
|
83
82
|
},
|
|
84
83
|
// Turbo's packages are the package manager's members, each a project
|
|
85
84
|
// with no vx.config written. `//#task` keys run on the root, as Turbo
|
package/src/workspace-plugins.ts
CHANGED
|
@@ -42,16 +42,21 @@ function entries(plugins: readonly WorkspacePlugin[], indent: string): string[]
|
|
|
42
42
|
return plugins.map((p) => `${indent}${p.factory}(),`)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
/** `run.concurrency` and
|
|
45
|
+
/** `baseBranch: 'main',` as its own line; `run.concurrency` and its group's other fields as one `run: { … }` line. */
|
|
46
46
|
function groupLines(
|
|
47
47
|
fields: readonly { readonly field: string; readonly source: string }[],
|
|
48
48
|
): string[] {
|
|
49
|
+
const top: string[] = []
|
|
49
50
|
const groups = new Map<string, string[]>()
|
|
50
51
|
for (const f of fields) {
|
|
51
|
-
const [group, key] = f.field.split('.') as [string, string]
|
|
52
|
-
|
|
52
|
+
const [group, key] = f.field.split('.') as [string, string | undefined]
|
|
53
|
+
if (key === undefined) top.push(` ${group}: ${f.source},`)
|
|
54
|
+
else groups.set(group, [...(groups.get(group) ?? []), `${key}: ${f.source}`])
|
|
53
55
|
}
|
|
54
|
-
return [
|
|
56
|
+
return [
|
|
57
|
+
...top,
|
|
58
|
+
...[...groups].map(([group, entries]) => ` ${group}: { ${entries.join(', ')} },`),
|
|
59
|
+
]
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
/** `.vx/workspace.<format>` declaring `plugins`. */
|