@xylabs/ts-scripts-yarn3 7.5.10 → 7.5.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xylabs/ts-scripts-yarn3",
3
- "version": "7.5.10",
3
+ "version": "7.5.12",
4
4
  "description": "TypeScript project scripts",
5
5
  "keywords": [
6
6
  "xylabs",
@@ -49,16 +49,18 @@
49
49
  "yargs": "~18.0.0"
50
50
  },
51
51
  "devDependencies": {
52
+ "@types/node": "^25.5.0",
52
53
  "@types/yargs": "~17.0.35",
53
- "@xylabs/ts-scripts-common": "~7.5.10",
54
- "@xylabs/tsconfig": "~7.5.10",
54
+ "@xylabs/ts-scripts-common": "~7.5.12",
55
+ "@xylabs/tsconfig": "~7.5.12",
55
56
  "publint": "~0.3.18",
56
57
  "tsup": "~8.5.1",
57
58
  "typescript": "^5.9.3",
58
- "vitest": "^4.1.1"
59
+ "vite": "^8.0.3",
60
+ "vitest": "^4.1.2"
59
61
  },
60
62
  "peerDependencies": {
61
- "@xylabs/ts-scripts-common": "~7.5.10",
63
+ "@xylabs/ts-scripts-common": "~7.5.12",
62
64
  "typescript": "~5"
63
65
  },
64
66
  "engines": {
@@ -0,0 +1,258 @@
1
+ ---
2
+ name: xylabs-xy-deplint-fix
3
+ description: >
4
+ Fix dependency declaration errors in one or more packages using `xy deplint`.
5
+ Use this skill whenever the user asks to fix deplint errors, clean up package.json
6
+ dependencies, or resolve "dependency should be devDependency" / "missing dependency"
7
+ warnings in an XY Labs monorepo. If a package name is supplied as an argument, fix
8
+ only that package. If no argument is given, fix all packages in the repo.
9
+ ---
10
+
11
+ # xylabs-xy-deplint-fix
12
+
13
+ Diagnoses and fixes `package.json` dependency declaration errors reported by `xy deplint`
14
+ in an XY Labs Yarn-workspaces monorepo.
15
+
16
+ ---
17
+
18
+ ## Bundled Scripts
19
+
20
+ Three shell scripts live alongside this skill in `scripts/`. They collapse multiple
21
+ bash operations into single approved calls, minimising permission prompts:
22
+
23
+ | Script | Purpose | Prompts saved |
24
+ |--------|---------|---------------|
25
+ | `scripts/deplint-scan.sh [pkg]` | Run deplint; emit structured `PACKAGE/ERROR/PATH/STATUS` lines | Replaces 1 raw deplint call with parseable output |
26
+ | `scripts/deplint-install.sh` | Run full `yarn install` (or `pnpm install`) from repo root | Always safe to approve once; never uses `workspaces focus` |
27
+ | `scripts/deplint-verify.sh pkg1 [pkg2 …]` | Check N packages in one call; prints `PASS/FAIL` per package | Replaces N individual verify calls with one |
28
+
29
+ **How to use them in the workflow:**
30
+
31
+ ```
32
+ Step 1 → bash scripts/deplint-scan.sh [pkg] # 1 approval
33
+ Step 3 → (LLM reads/writes package.json files) # no prompts
34
+ Step 4 → bash scripts/deplint-install.sh # 1 approval
35
+ Step 5 → bash scripts/deplint-verify.sh <pkgs…> # 1 approval
36
+ ```
37
+
38
+ All three scripts auto-detect the repo root (walking up until they find `yarn.lock`
39
+ or `pnpm-lock.yaml`), so they work correctly regardless of the current working directory.
40
+
41
+ ---
42
+
43
+ ## Package Manager Detection
44
+
45
+ Check the repo root before running any command:
46
+
47
+ * `yarn.lock` present → prefix commands with **yarn** (e.g. `yarn xy deplint`)
48
+ * `pnpm-lock.yaml` present → prefix commands with **pnpm**
49
+
50
+ All commands below are shown without a prefix. Prepend accordingly.
51
+
52
+ ---
53
+
54
+ ## Determine scope from arguments
55
+
56
+ * **Argument provided** (e.g. `@xyo-network/advertising-payload-plugins`) → single-package
57
+ mode: run Steps 1–5 for that package only, then stop.
58
+ * **No argument** → whole-repo mode: run `xy deplint` without a package name to get all
59
+ problems, extract the unique set of affected package names from the output, then run
60
+ Steps 1–5 for each affected package in turn.
61
+
62
+ ---
63
+
64
+ ## Step 1 — Run deplint
65
+
66
+ Use the bundled scan script (preferred — one approval, structured output):
67
+
68
+ ```bash
69
+ # Single-package
70
+ bash .claude/skills/xylabs-xy-deplint-fix/scripts/deplint-scan.sh @scope/package-name
71
+
72
+ # Whole-repo
73
+ bash .claude/skills/xylabs-xy-deplint-fix/scripts/deplint-scan.sh
74
+ ```
75
+
76
+ Output lines have the form:
77
+
78
+ ```
79
+ PACKAGE:@scope/package-name
80
+ ERROR:<problem description>:<dep>
81
+ PATH:packages/path/to/package.json
82
+ STATUS:errors # or STATUS:clean
83
+ ```
84
+
85
+ In whole-repo mode, collect every unique `PACKAGE:` line to build the list of packages
86
+ to fix. Work through them one at a time.
87
+
88
+ Alternatively, run deplint directly:
89
+
90
+ ```bash
91
+ xy deplint [package-name]
92
+ ```
93
+
94
+ Each problem line has the form:
95
+
96
+ ```
97
+ [@scope/package-name] <problem description>: <dependency-name>
98
+ <path/to/package.json>
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Step 2 — Classify each error
104
+
105
+ | Error message | Meaning | Fix |
106
+ |---|---|---|
107
+ | `dependency should be devDependency` | Listed in `dependencies` but not needed by npm consumers at runtime — it's a build/type/test dep, or it's a peer that consumers already provide | Move from `dependencies` → `devDependencies` |
108
+ | `Unused devDependency` | Listed in `devDependencies` but no import of it was found anywhere in the package's source | Remove from `devDependencies` |
109
+ | `Missing dependency` | Imported in source but absent from `dependencies` | Add to `dependencies` |
110
+ | `Missing devDependency` | Imported in source but absent from `devDependencies` | Add to `devDependencies` |
111
+
112
+ > **Aggregator packages** (packages with no `src/` that only re-export workspace children)
113
+ > typically need all of their workspace children as `devDependencies`, not `dependencies`.
114
+ > See Edge Cases below.
115
+
116
+ ---
117
+
118
+ ## Step 3 — Edit the package.json
119
+
120
+ Open the `package.json` file identified in the deplint output and apply the fix for each
121
+ classified error:
122
+
123
+ * **Move dep**: cut the entry from `dependencies`, paste into `devDependencies`.
124
+ * **Remove dep**: delete the entry entirely from `devDependencies`.
125
+ * **Add dep**: insert the entry with the correct version into the appropriate section.
126
+ Resolve the version using this priority order:
127
+
128
+ 1. **Workspace package** (highest priority) — check the `WORKSPACE:name:version` lines
129
+ emitted at the top of `deplint-scan.sh` output. If the dep name appears there, read
130
+ its version directly from that line and prefix with `~` (e.g. `5.3.7` → `~5.3.7`).
131
+ Never use the `workspace:` protocol — use the real semver version from the package.
132
+
133
+ 2. **Lock file** — for deps not in the workspace, search `yarn.lock` or `pnpm-lock.yaml`.
134
+ * In `yarn.lock`, look for a block starting with `"<pkg>@`:
135
+ ```
136
+ "@xyo-network/payload-model@npm:~5.3.5":
137
+ version: 5.3.7
138
+ ```
139
+ Use the declared range (e.g. `~5.3.5`), not the resolved exact version.
140
+ * In `pnpm-lock.yaml`, find the entry under `packages:` and use its
141
+ specifier (e.g. `~5.3.5`).
142
+
143
+ 3. **Another package.json in the repo** — if the lock file entry is unclear,
144
+ grep other `package.json` files in the monorepo for the dep name and
145
+ copy the version string used there.
146
+
147
+ 4. **Latest from the registry** — if the dep does not exist anywhere in the
148
+ repo yet, it is safe to use `~latest` by running:
149
+ ```bash
150
+ npm view <package-name> version
151
+ ```
152
+ Then prefix the result with `~` (e.g. `~5.4.0`).
153
+
154
+ **Version format rule:** prefer `~` ranges throughout. If the sourced version
155
+ already carries a range prefix (`~` or `^`), keep it as-is. If it is a bare
156
+ semver (e.g. `5.3.1`), add a `~` prefix (e.g. `~5.3.1`).
157
+ * If `dependencies` becomes empty after edits, remove the `"dependencies"` key entirely
158
+ to keep the file clean.
159
+
160
+ ---
161
+
162
+ ## Step 4 — Reinstall dependencies
163
+
164
+ After editing `package.json`, run a **full install from the repo root**. Do not use
165
+ `yarn workspaces focus` — it strips the `xy` scripts needed for verification.
166
+
167
+ Use the bundled install script (preferred — one approval, always runs from root):
168
+
169
+ ```bash
170
+ bash .claude/skills/xylabs-xy-deplint-fix/scripts/deplint-install.sh
171
+ ```
172
+
173
+ Or directly:
174
+
175
+ ```bash
176
+ yarn install # or: pnpm install
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Step 5 — Verify
182
+
183
+ Use the bundled verify script (preferred — verifies multiple packages in one approval):
184
+
185
+ ```bash
186
+ bash .claude/skills/xylabs-xy-deplint-fix/scripts/deplint-verify.sh <pkg1> [pkg2 …]
187
+ ```
188
+
189
+ Or directly:
190
+
191
+ ```bash
192
+ xy deplint <package-name>
193
+ ```
194
+
195
+ **Definition of done for a single package:** output contains `PASS: <name>` or:
196
+
197
+ ```
198
+ Deplint: Found no dependency problems. ✔
199
+ ```
200
+
201
+ If problems remain, return to Step 2 and repeat the loop for the same package.
202
+
203
+ ---
204
+
205
+ ## Step 6 — Advance to the next package (whole-repo mode only)
206
+
207
+ In whole-repo mode, once a package passes Step 5, move to the next package in the list
208
+ collected in Step 1 and repeat Steps 2–5 for it.
209
+
210
+ **Definition of done for whole-repo mode:** every package that appeared in the original
211
+ `xy deplint` output now passes `xy deplint <package-name>` individually. Confirm by
212
+ running a final `xy deplint` (no arguments) and verifying:
213
+
214
+ ```
215
+ Deplint: Found no dependency problems. ✔
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Edge Cases
221
+
222
+ ### `yarn workspaces focus` breaks the `xy` command
223
+
224
+ `yarn workspaces focus <package>` installs only the deps for that one package and removes
225
+ the root-level `xy` script bindings. Always use `yarn install` (full) after editing any
226
+ `package.json`.
227
+
228
+ ### Empty `dependencies` block after migration
229
+
230
+ If all entries are moved out of `dependencies`, remove the key entirely. An empty
231
+ `"dependencies": {}` is harmless but creates noise and may confuse other tools.
232
+
233
+ ### Formatter auto-sorts keys
234
+
235
+ The repo formatter (run as part of `yarn install` hooks) may re-sort `devDependencies`
236
+ alphabetically. This is expected — do not revert it.
237
+
238
+ ### Aggregator packages
239
+
240
+ Aggregator packages (e.g. `packages/payload/package.json`, `packages/sdk/package.json`)
241
+ have no `src/` and exist solely to re-export leaf packages. In these packages:
242
+
243
+ * Workspace child packages belong in `devDependencies`, not `dependencies`
244
+ * Their transitive deps (e.g. `@xyo-network/payload-model`) will also surface as
245
+ `Missing devDependency` because deplint walks the leaf source files from the
246
+ aggregator's root
247
+
248
+ Fix: move all workspace children to `devDependencies`, then add any missing transitive
249
+ deps (also as `devDependencies`).
250
+
251
+ ### `dependency should be devDependency` for a runtime import
252
+
253
+ deplint may flag a dep as "should be devDependency" even when it is imported for a
254
+ runtime value (not just a type). This happens when the dep is a **foundational library**
255
+ that consumers of the package are expected to already have installed (i.e. it behaves
256
+ like a peer). In these cases the correct fix is still to move it to `devDependencies`.
257
+ If the dep must be guaranteed for external npm consumers, also add it to
258
+ `peerDependencies`.
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ # deplint-install.sh
3
+ #
4
+ # Runs a full package install from the repo root using the detected package manager.
5
+ # Always installs from root — never uses scoped/filtered installs (yarn workspaces focus,
6
+ # pnpm --filter) as those strip the root xy script bindings needed for verification.
7
+ set -euo pipefail
8
+
9
+ find_repo_root() {
10
+ local dir="$PWD"
11
+ while [[ "$dir" != "/" ]]; do
12
+ [[ -f "$dir/yarn.lock" || -f "$dir/pnpm-lock.yaml" ]] && echo "$dir" && return
13
+ dir="$(dirname "$dir")"
14
+ done
15
+ echo "ERROR: repo root not found (no yarn.lock or pnpm-lock.yaml)" >&2
16
+ exit 1
17
+ }
18
+
19
+ REPO_ROOT="$(find_repo_root)"
20
+ cd "$REPO_ROOT"
21
+
22
+ # pnpm takes precedence over yarn — repos mid-migration may have both lock files
23
+ if [[ -f pnpm-lock.yaml ]]; then
24
+ pnpm install
25
+ else
26
+ yarn install
27
+ fi
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env bash
2
+ # deplint-scan.sh [package-name]
3
+ #
4
+ # Emits:
5
+ # WORKSPACE:name:version — for every non-root package in the monorepo
6
+ # PACKAGE:name — for each package with deplint errors
7
+ # ERROR:description:dep — for each error within that package
8
+ # PATH:path/to/package.json
9
+ # STATUS:clean|errors
10
+ #
11
+ # Usage:
12
+ # bash deplint-scan.sh # whole-repo scan
13
+ # bash deplint-scan.sh @scope/package-name # single-package scan
14
+ set -euo pipefail
15
+
16
+ find_repo_root() {
17
+ local dir="$PWD"
18
+ while [[ "$dir" != "/" ]]; do
19
+ [[ -f "$dir/yarn.lock" || -f "$dir/pnpm-lock.yaml" ]] && echo "$dir" && return
20
+ dir="$(dirname "$dir")"
21
+ done
22
+ echo "ERROR: repo root not found (no yarn.lock or pnpm-lock.yaml)" >&2
23
+ exit 1
24
+ }
25
+
26
+ REPO_ROOT="$(find_repo_root)"
27
+ cd "$REPO_ROOT"
28
+
29
+ # pnpm takes precedence over yarn — repos mid-migration may have both lock files
30
+ if [[ -f pnpm-lock.yaml ]]; then PM=pnpm; else PM=yarn; fi
31
+
32
+ # Emit WORKSPACE:name:version for every non-root package in the monorepo.
33
+ # Used by Step 3 to resolve versions for workspace-local deps without using
34
+ # the workspace: protocol (which npm publish does not rewrite).
35
+ find "$REPO_ROOT" -name "package.json" \
36
+ -not -path "*/node_modules/*" \
37
+ -not -path "$REPO_ROOT/package.json" | sort | \
38
+ node -e "
39
+ const fs = require('fs');
40
+ const rl = require('readline').createInterface({ input: process.stdin });
41
+ rl.on('line', f => {
42
+ try {
43
+ const p = JSON.parse(fs.readFileSync(f.trim(), 'utf8'));
44
+ if (p.name && p.version) process.stdout.write('WORKSPACE:' + p.name + ':' + p.version + '\n');
45
+ } catch(e) {}
46
+ });
47
+ " || true
48
+
49
+ # Run deplint — exits non-zero when errors are found, so capture output regardless
50
+ if [[ -n "${1:-}" ]]; then
51
+ deplint_out="$($PM xy deplint "$1" 2>&1)" || true
52
+ else
53
+ deplint_out="$($PM xy deplint 2>&1)" || true
54
+ fi
55
+
56
+ # Parse deplint output into structured lines
57
+ current_pkg=""
58
+ while IFS= read -r line; do
59
+ if [[ "$line" =~ ^\[([^]]+)\]\ (.+):\ (.+)$ ]]; then
60
+ pkg="${BASH_REMATCH[1]}"
61
+ if [[ "$pkg" != "$current_pkg" ]]; then
62
+ current_pkg="$pkg"
63
+ echo "PACKAGE:$pkg"
64
+ fi
65
+ echo "ERROR:${BASH_REMATCH[2]}:${BASH_REMATCH[3]}"
66
+ elif [[ "$line" =~ ^[[:space:]]+(.+package\.json)$ ]]; then
67
+ echo "PATH:${BASH_REMATCH[1]}"
68
+ fi
69
+ done <<< "$deplint_out"
70
+
71
+ if echo "$deplint_out" | grep -q "Found no dependency problems"; then
72
+ echo "STATUS:clean"
73
+ else
74
+ echo "STATUS:errors"
75
+ fi
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env bash
2
+ # deplint-verify.sh <package-name> [package-name ...]
3
+ #
4
+ # Verifies one or more packages pass deplint in a single approved call.
5
+ # Emits:
6
+ # PASS:name — package has no deplint errors
7
+ # FAIL:name — package still has deplint errors (details follow indented)
8
+ #
9
+ # Exits 0 only if every package passes.
10
+ set -euo pipefail
11
+
12
+ if [[ $# -eq 0 ]]; then
13
+ echo "Usage: deplint-verify.sh <package-name> [package-name ...]" >&2
14
+ exit 1
15
+ fi
16
+
17
+ find_repo_root() {
18
+ local dir="$PWD"
19
+ while [[ "$dir" != "/" ]]; do
20
+ [[ -f "$dir/yarn.lock" || -f "$dir/pnpm-lock.yaml" ]] && echo "$dir" && return
21
+ dir="$(dirname "$dir")"
22
+ done
23
+ echo "ERROR: repo root not found (no yarn.lock or pnpm-lock.yaml)" >&2
24
+ exit 1
25
+ }
26
+
27
+ REPO_ROOT="$(find_repo_root)"
28
+ cd "$REPO_ROOT"
29
+
30
+ # pnpm takes precedence over yarn — repos mid-migration may have both lock files
31
+ if [[ -f pnpm-lock.yaml ]]; then PM=pnpm; else PM=yarn; fi
32
+
33
+ all_passed=true
34
+
35
+ for pkg in "$@"; do
36
+ output="$($PM xy deplint "$pkg" 2>&1)" || true
37
+ if echo "$output" | grep -q "Found no dependency problems"; then
38
+ echo "PASS:$pkg"
39
+ else
40
+ echo "FAIL:$pkg"
41
+ echo "$output" | grep -E "^\[|^[[:space:]]" | sed 's/^/ /' || true
42
+ all_passed=false
43
+ fi
44
+ done
45
+
46
+ $all_passed || exit 1