# 本机离线资源库

本项目的统一资源库默认位于：

```text
/home/mes123456/resource-library/web-freecad-bitbybit
```

可通过 `WEB_FREECAD_RESOURCE_LIBRARY` 或各命令的 `--library=PATH` 改为其他位置。资源库不进入项目 Git；仓库保存资源定义，资源库自己的 `manifest.json` 保存每个归档和镜像的字节数、文件数、SHA-256、上游提交及工作树状态。

## 资源范围

`config/offline-resources.json` 固定以下资源：

- Node 22.23.2 原始发行包、两个 `package-lock.json` 对应的最小 npm 内容缓存，以及当前项目 `node_modules` 快照；
- FreeCAD 1.1.1（含 GSL、OndselSolver、AddonManager、测试子模块）、bitbybit、OCCT 8、OpenCAMLib、CAMotics/C! 和 LinuxCNC Web 工作树；
- FreeCAD headless/desktop Oracle、FreeCAD sysroot、OCCT/PlaneGCS 原生 Worker 制品和可选增量构建目录；
- Playwright Chromium/Firefox/WebKit、Boost/Eigen 头文件，以及本机 `/var/cache/apt/archives` 中的 Debian 安装包池。
- QtBase 6.8.2 源码、静态 wasm Qt6Core SDK 与可选增量构建缓存；源码包使用 Qt 官方 SHA-256 校验，国内 USTC 镜像仅作为传输源。

LinuxCNC 和 CAMotics 存在尚未合入各自上游提交的本地适配，因此保存完整工作树快照。`working_ocl/` 是上述源码的历史重复副本，不作为规范资源；构建入口实际使用的 `OpenCAMLib/`、`CAMotics/` 和 `.cache/bitbybit/bitbybit` 才进入资源库。

OCCT 增量构建缓存固定恢复到 `.cache/bitbybit/occt-history-build-offline`，其 CMake 缓存引用项目内 `.cache/occt/occt`，不包含旧工作区的绝对源码路径。

## 同步与校验

```bash
./npmw run offline:inventory
./npmw run offline:sync
./npmw run offline:check
./npmw run offline:smoke
```

`offline:sync` 只读取现有本机资源，不从互联网下载。首次同步会压缩数 GB 的源码和构建缓存；后续在上游提交、本地适配、工具链或 lockfile 变化后重新执行。

`offline:check` 逐项重新计算 SHA-256。`offline:smoke` 先在临时空目录用资源库 npm 缓存执行 `npm ci --offline`，再运行运行时/FreeCAD 源码/原生 Worker 检查和生产构建。npm 的 `--offline` 为强制模式，缺包时直接失败，不会访问 registry。资源库保持只读；离线 shell 按 manifest 哈希把 npm 内容初始化到项目 `.cache/offline-npm`，npm 的访问索引只写入这份工作缓存。

## 从资源库恢复

恢复操作必须显式限定资源，且默认拒绝覆盖现有目录：

```bash
./npmw run offline:restore -- --only=project-node-modules,freecad-source,occt-source
```

确认目标可替换后使用：

```bash
./npmw run offline:restore -- --only=project-node-modules --force
```

也可验证到独立临时工作目录：

```bash
target_dir="$(mktemp -d)"
./npmw run offline:restore -- --target="$target_dir" --only=freecad-source
```

不要对工作区根目录使用递归删除；恢复工具会检查每个目标必须位于指定 `--target` 下。

## 离线开发环境

以下命令启动一个明确禁止 npm 网络回退的 shell：

```bash
./scripts/offline-shell.sh
```

也可以直接运行单条命令：

```bash
./scripts/offline-shell.sh ./npmw run dev
./scripts/offline-shell.sh ./npmw run build
./scripts/offline-shell.sh ./npmw run ci:real -- --lane=wasm
```

环境中会设置 `npm_config_offline=true`、`PLAYWRIGHT_BROWSERS_PATH`、`FIREFOX_BIN`、`WEBKIT_BIN`、`FREECAD_SOURCE_OFFLINE=1`、项目内 `OCCT_SOURCE_DIR` 和固定 Chrome 路径。Firefox/WebKit 使用 manifest 中实际归档的可执行 revision，不要求它恰好等于当前 Playwright 包的默认下载 revision。Node bootstrap 在项目 `.runtime/downloads` 缺少发行包时也会先查资源库；设置 `WEB_FREECAD_OFFLINE=1` 后若资源库仍缺包，会直接失败而不调用 `curl`。

## 系统包恢复边界

源码、npm、Node、浏览器缓存和项目制品可以直接恢复到普通用户目录。CMake、Ninja、Emscripten、Chrome、Firefox、Qt、V8 和 FreeCAD 原生依赖属于 Debian 系统包；资源库保留了本机 apt 包池，并生成标准 `Packages`/`Packages.gz` 索引。安装系统包仍需要管理员权限。例如先把两个本地目录登记成仅本机 apt 源：

```bash
printf '%s\n' \
  'deb [trusted=yes] file:/home/mes123456/resource-library/web-freecad-bitbybit/system/debian13-amd64/packages ./' \
  'deb [trusted=yes] file:/home/mes123456/resource-library/web-freecad-bitbybit/system/debian13-amd64/freecad-packages ./' \
  | sudo tee /etc/apt/sources.list.d/web-freecad-offline.list
sudo apt-get update -o Dir::Etc::sourcelist=/etc/apt/sources.list.d/web-freecad-offline.list -o Dir::Etc::sourceparts=-
sudo apt-get --no-download install emscripten cmake ninja-build
```

这一步只在系统工具被卸载或重装主机时需要。日常断网开发直接使用当前已安装工具链。
