From b5e8665499116778fcdd0bbad2f12d7df28664d3 Mon Sep 17 00:00:00 2001 From: Atlas Zeng Date: Tue, 18 Aug 2026 20:29:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(bundle):=20=E8=81=9A=E5=90=88=E5=8F=8C?= =?UTF-8?q?=E6=8C=82=E8=BD=BD=E8=87=AA=E5=8A=A8=E9=80=80=E8=AE=A9=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20=E5=B7=B2=E6=9C=89=E5=90=8C=E5=8C=85?= =?UTF-8?q?=E5=90=8D=E5=90=AF=E7=94=A8=E6=8C=82=E8=BD=BD=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E6=8C=82=E8=87=AA=E5=B7=B1=20(#200)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(bundle): 聚合双挂载自动退让 —— 已有同包名启用挂载时不再挂自己 @linxin666/dsh-web-ui-all 等聚合包以独立条目 id(web-ui-better-sidebar) 挂载 dsh-better-sidebar 时,插件自身 bundle patch 的 better-sidebar 行会 与之双挂载:两个实例都注册 /sidebar/api,第二个抛 duplicate prefix route, 整个插件树启动失败。 better-sidebar 行的 disabled 改为 !!js 表达式:loader 按 entry-list 顺序 处理本行时,若已存在其他启用中的同包名挂载(排除自身 id),本行自动 disabled,由聚合行接管 sidebar。顺序假设(聚合 bundle 先于本包)写入注释。 - cordis.patch.yml:守卫表达式 + 说明注释 - README:常见问题「两个侧边栏」更新为自动退让说明 - scripts/e2e-aggregate-mount.sh:聚合双挂载真实挂载回归(scratch profile 聚合先行 + 插件后到 → boot 无 duplicate、/sidebar/api 存活) - tests/fixtures/aggregate-better-sidebar:最小聚合 fixture * ci(plugin-mount): 增加聚合双挂载回归 step 复用已装好的钉住版 DSH CLI 与已 pack 的 tarball,跑 scripts/e2e-aggregate-mount.sh(fixture 聚合先行 → 插件 bundle 行必须 自动退让,boot 无 duplicate prefix route)。 * fix(review): 双轴审查反馈——双语 README、注释补全、脚本健壮性 - README_EN.md:FAQ「两个侧边栏」行同步自动退让说明(双语惯例) - cordis.patch.yml:注释补上计划要求的「反向顺序为已知限制, 不引入运行时单例守卫」一句 - scripts/e2e-aggregate-mount.sh:TMP_DIR 纳入 trap 清理;FIXTURE_TGZ glob 加 2>/dev/null || true 让 die 路径生效; 花括号显式化 (LANG=UTF-8 下 bash 会把紧跟的全角字符吞进变量名,实测复现) - tests/fixtures/aggregate-better-sidebar/package.json:补 "type": "module" 与 lib/index.js 的 ESM 一致 * fix(e2e): 保护调用方提供的 DSH_HOME_BASE——只删除本调用拥有的子目录 chatgpt-codex-connector P2:当 DSH_HOME_BASE 指向已存在的目录(如开发者 真实 ~/.dsh)时,脚本会把 scratch profile 写进去并在退出时 rm -rf 整个 根目录。现在脚本始终在根目录下新建本调用拥有的独立子目录 (DSH_HOME_BASE/dsh-e2e-*.XXXXXX),只写入/删除该子目录;调用方提供的 目录本身绝不触碰。缺省路径仍用系统临时目录。 - scripts/e2e-aggregate-mount.sh:SCRATCH 子目录化 + 清理逻辑 - scripts/e2e-mount.sh:同款存量问题一并修复(bot 只审了 diff 内脚本) * test(e2e): 用真实 API 方法探活——terminal.deps 需返回 ok:true chatgpt-codex-connector P2:generic missing-route 404 无法证明 sidebar 路由真的注册了。新增对插件自身 handler /sidebar/api/terminal.deps 的 POST 探活,要求 HTTP 200 + {"ok":true};未知方法 404 保留为次要断言。 --- .github/workflows/ci.yml | 9 + README.md | 2 +- README_EN.md | 2 +- cordis.patch.yml | 15 ++ scripts/e2e-aggregate-mount.sh | 173 ++++++++++++++++++ scripts/e2e-mount.sh | 14 +- .../aggregate-better-sidebar/cordis.patch.yml | 7 + .../aggregate-better-sidebar/lib/index.js | 4 + .../aggregate-better-sidebar/package.json | 16 ++ 9 files changed, 237 insertions(+), 5 deletions(-) create mode 100755 scripts/e2e-aggregate-mount.sh create mode 100644 tests/fixtures/aggregate-better-sidebar/cordis.patch.yml create mode 100644 tests/fixtures/aggregate-better-sidebar/lib/index.js create mode 100644 tests/fixtures/aggregate-better-sidebar/package.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1fe97a7..ab55b88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,6 +94,15 @@ jobs: - name: Mount + headless-render smoke run: pnpm test:mount + # Aggregate double-mount regression: a fixture aggregate bundle mounts + # dsh-better-sidebar under its own entry id BEFORE the plugin's bundle + # row; the plugin must back off (no duplicate /sidebar/api, boot OK). + # Uses the pinned DSH CLI installed above. + - name: Aggregate double-mount regression + env: + DSH_CMD: dsh + run: bash scripts/e2e-aggregate-mount.sh + - name: Upload Playwright report on failure if: failure() uses: actions/upload-artifact@v4 diff --git a/README.md b/README.md index cf9227b..3b1fa80 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ dsh plugin --profile web add dsh-better-sidebar@latest | 报 `Ignored build scripts` | pnpm 11 拦截构建脚本。在 profile 目录(`~/.dsh/profiles/web`)跑 `pnpm approve-builds --all`。 | | 报 `minimum release age` / 版本不足 24h | 装的版本发布不足 24 小时。等 24h 或重跑一次(pnpm 会自动补 `minimumReleaseAgeExclude`)。 | | 报「找不到 profile 目录」 | 先跑一次 `dsh web`,让它初始化 `~/.dsh/profiles/web`。 | -| 页面出现**两个侧边栏** | 双挂载:`~/.dsh/profiles/web/cordis.patch.yml` 还留着旧的手动挂载行,删掉那段 `- insert: ... better-sidebar ...`。 | +| 页面出现**两个侧边栏** | 双挂载。旧的手动挂载行:`~/.dsh/profiles/web/cordis.patch.yml` 还留着 `- insert: ... better-sidebar ...`,删掉那段(同 id 重复挂载 loader 会直接报 `duplicate loader entry id`)。聚合包(如 `@linxin666/dsh-web-ui-all`)以**不同 id** 挂载本包时,0.13.x 起插件自身 bundle patch 会自动退让(检测到已有启用中的同包名挂载就不挂自己),无需手动处理;若仍双挂载,先确认聚合包的 bundle 顺序在 `dsh-better-sidebar` 之前。 | | Windows 下终端无法使用 | `node-pty` 依赖预编译二进制;若当前 Node 版本没有对应产物,需装编译工具链(VS Build Tools)。主流 Node 版本一般已有预编译。 | | 终端提示「node-pty 加载失败」 | `node-pty` 安装缺失/损坏(如 pnpm 拦截了构建脚本)。终端横幅会给出修复命令:复制到 DSH 所在环境的终端/cmd 执行(在 `~/.dsh/profiles/web` 下 `pnpm approve-builds --all && pnpm rebuild node-pty`),完成后重启 DSH 并点重试。插件与 DSH 核心使用同一 `node-pty@^1.1.0`,修复后两者同步恢复。 | | 提示 `dsh: command not found` | 先安装 DSH;或直接用 `npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-better-sidebar@latest`。 | diff --git a/README_EN.md b/README_EN.md index fbe6b7d..51e39fc 100644 --- a/README_EN.md +++ b/README_EN.md @@ -128,7 +128,7 @@ or bump the version in `~/.dsh/profiles/web/package.json` (e.g. `"^0.13.0"`) and | `Ignored build scripts` | pnpm 11 blocked build scripts. Run `pnpm approve-builds --all` in the profile directory (`~/.dsh/profiles/web`). | | `minimum release age` / version `< 24h` | The release is younger than 24 hours. Wait, or re-run once (pnpm auto-adds `minimumReleaseAgeExclude`). | | "profile directory not found" | Run `dsh web` once so it initializes `~/.dsh/profiles/web`. | -| Two sidebars on the page | Double-mount: `~/.dsh/profiles/web/cordis.patch.yml` still has the old hand-written `- insert: ... better-sidebar ...` line — delete it. | +| Two sidebars on the page | Double-mount. Old hand-written line: `~/.dsh/profiles/web/cordis.patch.yml` still has `- insert: ... better-sidebar ...` — delete it (a same-id duplicate mount makes the loader fail loudly with `duplicate loader entry id`). When an aggregate bundle (e.g. `@linxin666/dsh-web-ui-all`) mounts this package under a **different** id, the plugin's own bundle patch backs off automatically since 0.13.x (it detects an already-enabled mount of the same package name and does not mount itself) — no manual fix needed; if it still double-mounts, make sure the aggregate bundle precedes `dsh-better-sidebar` in `dsh.profile.bundles`. | | Terminal fails on Windows | `node-pty` relies on prebuilt binaries; if none match your Node version, install a build toolchain (VS Build Tools). Mainstream Node versions are usually covered. | | Terminal shows "node-pty failed to load" | The `node-pty` install is missing or broken (e.g. pnpm skipped its build script). The terminal banner shows a repair command — copy it into a terminal/cmd on the DSH machine and run it (in `~/.dsh/profiles/web`: `pnpm approve-builds --all && pnpm rebuild node-pty`), then restart DSH and click Retry. The plugin and DSH core share the same `node-pty@^1.1.0`, so the repair restores both. | | `dsh: command not found` | Install DSH first, or run `npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-better-sidebar@latest`. | diff --git a/cordis.patch.yml b/cordis.patch.yml index 193675a..420076f 100644 --- a/cordis.patch.yml +++ b/cordis.patch.yml @@ -29,6 +29,21 @@ # shellArgs: # - --noprofile # - --no-rc +# +# Aggregate double-mount guard: aggregate bundles (e.g. @linxin666/dsh-web-ui-all) +# may already mount this package under their own entry id (e.g. +# `web-ui-better-sidebar`). Two mounts register /sidebar/api twice and fail the +# whole plugin tree at boot ("duplicate prefix route"). The `!!js` disabled +# expression backs THIS row off when another *enabled* entry already mounts +# `dsh-better-sidebar`; the aggregate instance then owns the sidebar. The +# loader evaluates it when this row is processed (entry-list order, only rows +# before this one are visible), so the aggregate bundle must precede this one +# in `dsh.profile.bundles` — the standard install order, since `dsh plugin add` +# appends new bundles last. The reverse order (this bundle before the +# aggregate) is a known limitation: the guard cannot see rows that come after +# it, and no runtime singleton guard is added. Same-id manual duplicates still +# fail loudly at the loader as before. - insert: - id: better-sidebar name: 'dsh-better-sidebar' + disabled: !!js "[...ctx.loader.entries()].some((e) => e.options.name === 'dsh-better-sidebar' && e.options.id !== 'better-sidebar' && !e.disabled)" diff --git a/scripts/e2e-aggregate-mount.sh b/scripts/e2e-aggregate-mount.sh new file mode 100755 index 0000000..12066dc --- /dev/null +++ b/scripts/e2e-aggregate-mount.sh @@ -0,0 +1,173 @@ +#!/usr/bin/env bash +# ============================================================================= +# dsh-better-sidebar 聚合双挂载冒烟(CI + 本地): +# +# 场景:一个聚合 bundle(tests/fixtures/aggregate-better-sidebar)先以独立 +# 条目 id 挂载 dsh-better-sidebar,插件自身的 bundle patch 后到 —— 旧行为 +# 两个实例都注册 /sidebar/api,整个插件树启动失败(duplicate prefix +# route);新行为插件行检测到已有启用中的同包名挂载后自动 disabled,由 +# 聚合行接管 sidebar。 +# +# 流程: +# 1. 打包 fixture 聚合包; +# 2. 用官方 CLI 把 fixture 先装进全新 scratch profile,再把插件 tarball +# 装进同一 profile(复刻真实安装顺序:聚合先行、dsh plugin add 后到); +# 3. 启动真实 `dsh web`(keyless,--port 0); +# 4. 断言:日志出现启动 URL、无 "duplicate prefix route"、/sidebar/api +# 路由存活(POST 未知方法应返回 404 JSON 而非崩溃)。 +# +# 用法: +# bash scripts/e2e-aggregate-mount.sh +# +# 环境变量(均可省略): +# DSH_CMD dsh 命令;缺省 `npx -y --package @deepseek-ai/dsh dsh` +# (与 pm2 启动器同源,避免依赖可能失效的 PATH dsh) +# TARBALL 插件 tarball;缺省仓库根 dsh-better-sidebar-*.tgz(须已 pack) +# PORT 固定端口(默认 0 = OS 分配,从日志解析 URL) +# DSH_HOME_BASE scratch 根目录(默认系统临时目录)。脚本始终在其下新建 +# 本调用拥有的独立子目录,只写入/删除该子目录;调用方提供 +# 的目录本身(可能是真实 ~/.dsh)绝不写入或删除。 +# KEEP_HOME 非空时保留 scratch 目录(调试用) +# +# 退出码 = 0 通过;非 0 失败。服务器与 scratch 目录由 trap 兜底清理。 +# ============================================================================= +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +FIXTURE_DIR="$ROOT/tests/fixtures/aggregate-better-sidebar" + +DSH_CMD="${DSH_CMD:-npx -y --package @deepseek-ai/dsh dsh}" +TARBALL="${TARBALL:-}" +PORT="${PORT:-0}" +KEEP_HOME="${KEEP_HOME:-}" + +say() { printf '\033[32m[e2e-aggregate-mount]\033[0m %s\n' "$*"; } +warn() { printf '\033[33m[e2e-aggregate-mount]\033[0m %s\n' "$*" >&2; } +die() { printf '\033[31m[e2e-aggregate-mount]\033[0m %s\n' "$*" >&2; exit 1; } + +command -v node >/dev/null 2>&1 || die "未找到 node(DSH 运行需要 Node.js >= 20)" +command -v pnpm >/dev/null 2>&1 || die "未找到 pnpm(dsh plugin 转发给 pnpm)" +command -v npm >/dev/null 2>&1 || die "未找到 npm(打包 fixture 需要)" +command -v curl >/dev/null 2>&1 || die "未找到 curl" + +if [ -z "$TARBALL" ]; then + TARBALL="$(ls "$ROOT"/dsh-better-sidebar-*.tgz 2>/dev/null | head -1 || true)" +fi +[ -n "$TARBALL" ] && [ -f "$TARBALL" ] || die "未找到插件 tarball:先在本仓库跑 pnpm build && npm pack,或用 TARBALL 指定" + +# ── scratch home ──────────────────────────────────────────────────────────── +# 始终在本调用拥有的全新目录里运行:调用方给了 DSH_HOME_BASE(可能是真实 +# ~/.dsh)时,只在其下新建子目录并只删除该子目录;缺省时直接用系统临时 +# 目录。调用方提供的目录本身绝不写入或删除。 +DSH_HOME_BASE="${DSH_HOME_BASE:-}" +if [ -n "$DSH_HOME_BASE" ]; then + SCRATCH="$(mktemp -d "$DSH_HOME_BASE/dsh-e2e-agg.XXXXXX")" +else + SCRATCH="$(mktemp -d /tmp/dsh-e2e-agg.XXXXXX)" +fi +export DSH_HOME="$SCRATCH" +LOG_DIR="$DSH_HOME/logs"; mkdir -p "$LOG_DIR" +OUT_LOG="$LOG_DIR/dsh-web.out.log"; ERR_LOG="$LOG_DIR/dsh-web.err.log" +SERVER_PID="" +TMP_DIR="" +cleanup() { + if [ -n "$SERVER_PID" ] && kill -0 "$SERVER_PID" 2>/dev/null; then + kill "$SERVER_PID" 2>/dev/null || true + wait "$SERVER_PID" 2>/dev/null || true + fi + if [ -n "$TMP_DIR" ] && [ -d "$TMP_DIR" ]; then + rm -rf "$TMP_DIR" + fi + if [ -z "$KEEP_HOME" ] && [ -d "$SCRATCH" ]; then + rm -rf "$SCRATCH" + else + warn "KEEP_HOME 已设置,保留 $SCRATCH" + fi +} +trap cleanup EXIT + +# ── 打包 fixture 聚合包 ───────────────────────────────────────────────────── +TMP_DIR="$(mktemp -d)" +( cd "$FIXTURE_DIR" && npm pack --silent --pack-destination "$TMP_DIR" >/dev/null ) +FIXTURE_TGZ="$(ls "$TMP_DIR"/*.tgz 2>/dev/null | head -1 || true)" +[ -n "$FIXTURE_TGZ" ] || die "fixture 打包失败" + +# ── 引导 scratch profile(web 模板)──────────────────────────────────────── +# 先写 pnpm-workspace.yaml 的 allowBuilds / minimumReleaseAgeExclude,避免 +# pnpm 11 strict-dep-builds 拦截 node-pty/protobufjs——同 e2e-mount.sh。 +PROFILE_DIR="$DSH_HOME/profiles/web" +mkdir -p "$PROFILE_DIR" +cat > "$PROFILE_DIR/package.json" < "$PROFILE_DIR/cordis.patch.yml" +cat > "$PROFILE_DIR/pnpm-workspace.yaml" <<'EOF' +packages: + - . + +nodeLinker: hoisted +autoInstallPeers: false + +allowBuilds: + node-pty: true + protobufjs: true + +minimumReleaseAgeExclude: + - dsh-better-sidebar +EOF + +# ── 组装 profile:聚合先行,插件后到 ────────────────────────────────────── +say "安装 fixture 聚合包(先行)…" +$DSH_CMD plugin --profile web add "file:$FIXTURE_TGZ" +say "安装插件 tarball(后到)…" +$DSH_CMD plugin --profile web add "file:$TARBALL" + +# ── 启动真实 dsh web ─────────────────────────────────────────────────────── +say "启动 dsh web(--port ${PORT},日志 ${LOG_DIR})…" +$DSH_CMD web --port "$PORT" >"$OUT_LOG" 2>"$ERR_LOG" & +SERVER_PID=$! + +# 等待启动 URL 或进程退出(最多 120s) +URL="" +for _ in $(seq 1 120); do + if ! kill -0 "$SERVER_PID" 2>/dev/null; then break; fi + URL="$(grep -oE 'http://127\.0\.0\.1:[0-9]+' "$OUT_LOG" | tail -1 || true)" + [ -n "$URL" ] && break + sleep 1 +done +if [ -z "$URL" ]; then + warn "out log 尾部:$(tail -5 "$OUT_LOG" 2>/dev/null || true)" + warn "err log 尾部:$(tail -5 "$ERR_LOG" 2>/dev/null || true)" + die "dsh web 未在 120s 内启动" +fi +say "已启动:$URL" + +# ── 断言 ──────────────────────────────────────────────────────────────────── +if grep -q "duplicate prefix route" "$ERR_LOG" "$OUT_LOG" 2>/dev/null; then + die "检测到 duplicate prefix route(双挂载未退让)" +fi + +# 真实方法探活:terminal.deps 是插件自己的 handler(writeOk → HTTP 200 + +# {"ok":true,...})。成功响应证明至少一个实例真正注册了 /sidebar/api 路由 +# ——generic missing-route 404 无法冒充(P2: Probe a real sidebar API method)。 +DEPS="$(curl -s -X POST "$URL/sidebar/api/terminal.deps" 2>/dev/null || true)" +if ! printf '%s' "$DEPS" | grep -q '"ok":true'; then + die "/sidebar/api/terminal.deps 未返回 ok:true(响应:$(printf '%s' "$DEPS" | head -c 200))" +fi +say "/sidebar/api/terminal.deps → ok:true(真实 handler 存活)" + +STATUS="$(curl -s -o /dev/null -w '%{http_code}' -X POST "$URL/sidebar/api/__e2e_unknown__" 2>/dev/null || true)" +say "/sidebar/api POST 未知方法 → HTTP ${STATUS}(期望 404)" +[ "$STATUS" = "404" ] || die "/sidebar/api 未知方法未按预期返回 404(HTTP ${STATUS})" + +say "通过:聚合双挂载场景下插件自动退让,侧边栏由聚合行接管。" diff --git a/scripts/e2e-mount.sh b/scripts/e2e-mount.sh index ba12c7d..983d08b 100755 --- a/scripts/e2e-mount.sh +++ b/scripts/e2e-mount.sh @@ -16,7 +16,9 @@ # DSH_CMD dsh 命令;缺省 PATH 上的 `dsh`,回退 npx 拉官方包 # TARBALL 插件 tarball;缺省仓库根 dsh-better-sidebar-*.tgz(须已 pack) # PORT 固定端口(默认 0 = OS 分配,从日志解析 URL) -# DSH_HOME_BASE 覆盖 scratch 根目录(默认 mktemp -d) +# DSH_HOME_BASE 覆盖 scratch 根目录(默认系统临时目录)。脚本始终在其下 +# 新建本调用拥有的独立子目录,只写入/删除该子目录;调用方 +# 提供的目录本身(可能是真实 ~/.dsh)绝不写入或删除。 # KEEP_HOME 非空时保留 scratch home(调试用) # # 退出码 = playwright 的退出码;服务器与 scratch 目录由 trap 兜底清理。 @@ -57,8 +59,14 @@ fi TARBALL="$(cd "$(dirname "$TARBALL")" && pwd)/$(basename "$TARBALL")" say "tarball: $TARBALL" -# scratch home(每次全新,绝不触碰真实 ~/.dsh) -SCRATCH="${DSH_HOME_BASE:-$(mktemp -d /tmp/dsh-e2e-mount.XXXXXX)}" +# scratch home(每次全新,绝不触碰真实 ~/.dsh):调用方给了 DSH_HOME_BASE +# 时,只在其下新建本调用拥有的子目录并只删除该子目录;缺省时直接用系统 +# 临时目录。 +if [ -n "${DSH_HOME_BASE:-}" ]; then + SCRATCH="$(mktemp -d "$DSH_HOME_BASE/dsh-e2e-mount.XXXXXX")" +else + SCRATCH="$(mktemp -d /tmp/dsh-e2e-mount.XXXXXX)" +fi export DSH_HOME="$SCRATCH/home" WORKSPACE_DIR="$SCRATCH/workspace" LOG_DIR="$SCRATCH" diff --git a/tests/fixtures/aggregate-better-sidebar/cordis.patch.yml b/tests/fixtures/aggregate-better-sidebar/cordis.patch.yml new file mode 100644 index 0000000..8501355 --- /dev/null +++ b/tests/fixtures/aggregate-better-sidebar/cordis.patch.yml @@ -0,0 +1,7 @@ +# Fixture aggregate bundle: mounts dsh-better-sidebar under its own entry id, +# the way real aggregate bundles (e.g. @linxin666/dsh-web-ui-all) do. Used by +# scripts/e2e-aggregate-mount.sh to prove the plugin's own bundle patch backs +# off when another enabled entry already mounts the same package. +- insert: + - id: aggregate-better-sidebar + name: 'dsh-better-sidebar' diff --git a/tests/fixtures/aggregate-better-sidebar/lib/index.js b/tests/fixtures/aggregate-better-sidebar/lib/index.js new file mode 100644 index 0000000..c688ea6 --- /dev/null +++ b/tests/fixtures/aggregate-better-sidebar/lib/index.js @@ -0,0 +1,4 @@ +// No-op plugin body. This fixture only carries a patch layer (see +// cordis.patch.yml); no entry ever references this package by name, but the +// main file keeps npm pack's manifest valid. +export function apply() {} diff --git a/tests/fixtures/aggregate-better-sidebar/package.json b/tests/fixtures/aggregate-better-sidebar/package.json new file mode 100644 index 0000000..31c6ebd --- /dev/null +++ b/tests/fixtures/aggregate-better-sidebar/package.json @@ -0,0 +1,16 @@ +{ + "name": "fixture-aggregate-better-sidebar", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "lib/index.js", + "files": [ + "lib", + "cordis.patch.yml" + ], + "dsh": { + "bundle": { + "patch": "./cordis.patch.yml" + } + } +}