@adep/cli 0.4.4 → 0.4.6

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.
Files changed (46) hide show
  1. package/README.md +107 -11
  2. package/dist/index.js +33802 -27354
  3. package/dist/vite.js +247 -17
  4. package/dist/worker-entry.js +163 -1
  5. package/package.json +7 -6
  6. package/templates/app-desktop/README.md +67 -2
  7. package/templates/app-desktop/identity-store.mjs +309 -0
  8. package/templates/app-desktop/identity.mjs +517 -0
  9. package/templates/app-desktop/main.cjs +17 -0
  10. package/templates/app-desktop/main.mjs +218 -2
  11. package/templates/app-desktop/offline-runtime.mjs +72 -3
  12. package/templates/app-desktop/package.json +10 -6
  13. package/templates/app-desktop/recovery-ui.mjs +300 -0
  14. package/templates/app-desktop/sync-loop.mjs +137 -0
  15. package/templates/app-mobile/README.md +47 -9
  16. package/templates/app-mobile/package.json +2 -1
  17. package/templates/app-mobile/plugins/adep-bridge/Package.swift +5 -1
  18. package/templates/app-mobile/plugins/adep-bridge/android/build.gradle +34 -3
  19. package/templates/app-mobile/plugins/adep-bridge/android/src/main/AndroidManifest.xml +12 -5
  20. package/templates/app-mobile/plugins/adep-bridge/android/src/main/java/com/adep/bridge/AdepBridge.kt +198 -12
  21. package/templates/app-mobile/plugins/adep-bridge/android/src/main/java/com/adep/bridge/AdepIdentity.kt +342 -0
  22. package/templates/app-mobile/plugins/adep-bridge/android/src/main/java/com/adep/bridge/AdepKeystore.kt +56 -2
  23. package/templates/app-mobile/plugins/adep-bridge/android/src/main/java/com/adep/bridge/AdepSqlite.kt +506 -0
  24. package/templates/app-mobile/plugins/adep-bridge/android/src/main/java/com/adep/bridge/AdepSqliteLogic.kt +235 -0
  25. package/templates/app-mobile/plugins/adep-bridge/dist/plugin.js +30 -0
  26. package/templates/app-mobile/plugins/adep-bridge/ios/AdepBridge.podspec +3 -0
  27. package/templates/app-mobile/plugins/adep-bridge/ios/Sources/AdepBridge.swift +221 -9
  28. package/templates/app-mobile/plugins/adep-bridge/ios/Sources/AdepIdentity.swift +500 -0
  29. package/templates/app-mobile/plugins/adep-bridge/ios/Sources/AdepKeychain.swift +69 -17
  30. package/templates/app-mobile/plugins/adep-bridge/ios/Sources/AdepPermissionGate.swift +25 -4
  31. package/templates/app-mobile/plugins/adep-bridge/ios/Sources/AdepShellConfig.swift +54 -0
  32. package/templates/app-mobile/plugins/adep-bridge/ios/Sources/AdepSqlite.swift +614 -0
  33. package/templates/app-mobile/plugins/adep-bridge/package.json +10 -0
  34. package/templates/app-mobile/template.json +12 -3
  35. package/templates/app-mobile/web/adep-bridge.js +103 -9
  36. package/templates/app-mobile/web/offline-runtime.js +230 -0
  37. package/templates/app-mobile-xtool/AdepShell-Info.plist +24 -0
  38. package/templates/app-mobile-xtool/Package.swift +59 -0
  39. package/templates/app-mobile-xtool/README.md +81 -0
  40. package/templates/app-mobile-xtool/Sources/AdepShell/App.swift +36 -0
  41. package/templates/app-mobile-xtool/Sources/AdepShell/ShellViewController.swift +223 -0
  42. package/templates/app-mobile-xtool/adep.permissions.json +4 -0
  43. package/templates/app-mobile-xtool/app/site/.gitkeep +0 -0
  44. package/templates/app-mobile-xtool/template.json +15 -0
  45. package/templates/app-mobile-xtool/xtool.yml +35 -0
  46. package/templates/app-mobile/plugins/adep-bridge/capacitor.plugin.json +0 -10
package/README.md CHANGED
@@ -520,6 +520,7 @@ adep export --out ./dist-export # 指定输出目录(缺省 ./exports)
520
520
  ```bash
521
521
  adep app init -p my-app -n "我的应用" # 生成 Electron 壳工程(缺省 ./my-app-app)
522
522
  cd my-app-app && npm install # 壳工程依赖(electron + electron-builder)
523
+ adep app open # 启动开发预览(等价壳工程内 npm start,构建前先跑一眼)
523
524
 
524
525
  adep app build # 拉取已发布页面产物 → 注入 app/site/ → 出安装包
525
526
  adep app build --platform win32 # 交叉指定目标平台(缺省当前平台)
@@ -530,6 +531,16 @@ adep app build --prepare-only # 只拉产物 + 注入 + 出构建
530
531
  - `app build` 只把项目**已发布**的前端产物(`adep publish --only frontend` 的产物)打进壳:
531
532
  经平台导出链路拉包 → 校验 manifest 与逐项 sha256 → 只取 `site/**` 注入 `app/site/`
532
533
  (注入前清空旧产物,上一次构建留下的陈旧文件不会躺在安装包里);
534
+ - **缺省产物形态**(APP-037 契约门锁住,漂移当场红):
535
+
536
+ | 平台 | 缺省格式 | 签名状态 | 说明 |
537
+ | -------------------- | ------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
538
+ | macOS(`darwin`) | `.dmg` | unsigned | 签名 / 公证由开发者本地完成 |
539
+ | Windows(`win32`) | nsis 安装器(`*-Setup.exe`)+ zip 便携包(`*-win.zip`) | unsigned | 安装器**不是单文件绿色 exe**;zip 便携包(APP-043)解压后直接运行里面的 `<productName>.exe`,两者同次产出 |
540
+ | Linux(`linux`) | `.AppImage` + `.deb` | unsigned | deb 需要宿主机有 `dpkg-deb`——缺失时 electron-builder 会静默跳过,构建报告与终端会显式列出 `APP_BUILD_TARGET_SKIPPED` 及原因(rpm 不进缺省模板,见计划 R2 拍板 P3) |
541
+ | Android(`android`) | unsigned `.apk` | unsigned | `gradlew assembleRelease`,签名由开发者自担 |
542
+ | iOS(`ios`) | unsigned `.xcarchive` / `.ipa` | unsigned | xcodebuild 或 xtool(`--toolchain xtool` 产 `.ipa`) |
543
+
533
544
  - **函数源码不入包**:在线运行时下函数在服务端执行,构建报告里的函数清单只标
534
545
  `runtime: "online"`(安装包内不含任何 `functions/` 文件);
535
546
  - 产物版本回写 `adep.app.json` 的 `build` 段(`bundleVersion` = manifest 项目版本 + `site/` 内容指纹,
@@ -539,6 +550,12 @@ adep app build --prepare-only # 只拉产物 + 注入 + 出构建
539
550
  - fail loud(都以退出码 1 结束且不产出安装包):项目从未发布前端(提示先跑
540
551
  `publish --only frontend`)、壳工程依赖未安装(提示先 `npm install`)、导出包损坏或内容物校验和不匹配。
541
552
  其中「依赖未安装」的判定**有意排在导出之前**——导出是分钟级长任务,依赖没装不必白跑。
553
+ - `app open`(APP-035)只服务桌面壳:直接调壳工程内安装的 `node_modules/.bin/electron .`
554
+ (与模板缺省 start script `electron .` 等价,不经 npm 以规避 Windows 下 npm.cmd 的 shell 差异;
555
+ 若你改过 start script,open 不感知,直接跑 `npm start` 即可)。**移动壳没有开发预览路径**
556
+ (capacitor 壳下一步是 `npx cap add ios / android` + Xcode / Android Studio,xtool 壳是 `xtool dev`),
557
+ 对它们执行 open 当场报 `APP_OPEN_UNSUPPORTED` 并点名下一步。与 `app doctor` 同口径的开发期
558
+ 便利命令:不需要登录、不需要网络、不设门(判定门在 `app build`)。
542
559
 
543
560
  #### 移动壳(Capacitor,APP-009)
544
561
 
@@ -555,22 +572,100 @@ adep app build --platform ios # xcodebuild archive(
555
572
  - 骨架含 `plugins/adep-bridge` **原生桥**(iOS Swift / Android Kotlin)与 host-side 门控镜像
556
573
  `bridge/gate.mjs`:权限门控做在**原生侧**,未在 `adep.permissions.json` 声明的权限一律
557
574
  `PERMISSION_DENIED` + 设备侧审计日志;`ownerKey` 只存 Keychain / Keystore。
575
+ - 构建往 `app/site/` 落四件:`adep.permissions.json`(权限清单)、`adep-bridge.js`(页面桥)、
576
+ `adep.app.json`(壳配置)、以及往 `index.html` 幂等注入的一行 `<script src="/adep-bridge.js">`。
577
+ **缺 `index.html` 即构建失败**(`APP_SITE_MISSING`):它是 WebView 恒加载的入口页,缺了装机就是
578
+ 白屏——所以不产出「报告成功、装机白屏」的包。页面加载后由桥装配 `window.__ADEP_APP__`,
579
+ 失败时按原因分三种字段(`configError` / `offlineError` / `timeoutError`),都带可读原因,
580
+ 不会只剩一个 `MISSING`。
558
581
  - iOS 侧原生桥是**双形态并存**(APP-015):`Package.swift`(SPM)与 `ios/AdepBridge.podspec`
559
582
  (CocoaPods)各管一条消费路径。自 Capacitor 8 起 `cap add ios` 默认建 SPM 工程,缺 SPM 清单的
560
583
  插件会被**静默跳过**(运行时才报 "plugin is not implemented"),所以两者都别删;包名 / product 名
561
584
  (`AdepBridge`)、目录布局(清单在 npm 包根、源码平铺 `ios/Sources`)与 iOS 下限(14.0)两形态必须一致。
562
585
  - 移动平台**必须显式指定** `--platform ios|android`;产物是 **unsigned** 的 `.xcarchive` / APK。
586
+ - ⚠️ **`.xcarchive` ≠ 安装包**(APP-040):它是 Xcode 的归档格式,不能直接装真机;导出 `.ipa`
587
+ 还需要在 Xcode 里完成 Distribute App(或 `xcodebuild -exportArchive`),而导出要**用户自备**
588
+ `ExportOptions.plist` 与描述文件——平台不出具签名(PRD §2.11.7),这一步不做自动化
589
+ (见 `docs/mobile-shell-signing.md` §3)。构建期会对 `.xcarchive` 做产物级结构核对:
590
+ 缺 `Products/Applications/*.app` 报 `APP_ARCHIVE_INCOMPLETE`;归档内出现
591
+ `_CodeSignature` / `embedded.mobileprovision` 报 `APP_ARCHIVE_SIGNED`(与「平台不出具签名」
592
+ 口径冲突,属实现回归)。
563
593
  - 签名 / 公证 / 上架由开发者自担,逐步指引见仓库 `docs/mobile-shell-signing.md`。
564
594
 
565
- #### 离线运行时(`--offline`,APP-008)
595
+ #### 离线运行时(`--offline`,APP-008 / APP-022)
596
+
597
+ ```bash
598
+ adep app build --offline # 桌面壳:注入 app/offline/
599
+ adep app build --offline --toolchain xtool # iOS xtool 壳:注入 app/site/offline/
600
+ ```
601
+
602
+ 把设备端运行时(`@adep/app-runtime`)装入壳工程的离线根——桌面 `app/offline/`,xtool
603
+ `app/site/offline/`(页面经 `capacitor://` 只能读 `appLocation` 之内的文件):白名单云函数与
604
+ 数据库基线表全部**随包本地执行**,不需要平台在线。白名单函数含**不可移植**写法时构建失败、
605
+ 退出码非 0,错误含违规类型与文件名行号。
606
+
607
+ `--offline` 在**桌面壳**下不接受 `--platform`(离线包与平台无关);iOS 走
608
+ `--offline --toolchain xtool`(恒 `--platform ios`)。
609
+
610
+ ⚠️ **xtool 离线构建要求先跑在线构建**:离线路径只追加 `site/offline/` 子树与壳注入面
611
+ (页面桥 / `adep.app.json` / 权限清单),**不产生页面本体**——页面只能来自平台导出。
612
+ 缺 `app/site/index.html` 时当场报 `APP_SITE_MISSING`,不会产出「报告成功、装机白屏」的包。
613
+
614
+ ```bash
615
+ adep app build --platform ios --toolchain xtool # 1) 拉页面产物 + 注入页面桥 / 壳配置
616
+ adep app build --offline --toolchain xtool # 2) 追加离线树
617
+ ```
618
+
619
+ #### 壳工程体检(`adep app doctor`,APP-031)
620
+
621
+ ```bash
622
+ adep app doctor # 体检当前目录(壳工程根)
623
+ adep app doctor --dir ./my-app-app # 指定壳工程
624
+ adep app doctor --json # 机器可读(脚本 / CI 归档)
625
+ ```
626
+
627
+ **只读、不需要登录、不需要网络**:体检的是「盘上已经有的东西」。它与 `app build` 的分工是场景不同——
628
+ build 要先登录、先发布、跑一整轮导出才知道注入面齐不齐;doctor 一条离线命令就回答同一个问题,
629
+ 适合排查「上次构建留下的壳工程为什么装机白屏」。十项结论各带固定 `id` 与原因码(与构建侧同码):
630
+
631
+ | id | 查什么 | 不通过时 |
632
+ | -------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
633
+ | `config` | `adep.app.json` 在且过 schema | `APP_CONFIG_NOT_FOUND` / `APP_CONFIG_INVALID`(读不到就当场收口,不再往下猜) |
634
+ | `form` | 由 `template` 推导构建形态(desktop→electron;mobile→capacitor + 盘上原生工程;xtool→xtool/ios) | 还没 `npx cap add` / 未知模板 ⇒ 提示 |
635
+ | `deps` | 打包器前置(复用构建侧判定,不写盘) | `APP_SHELL_DEPS_MISSING` / `APP_XTOOL_MISSING` / `APP_XCODE_SDK_MISSING` |
636
+ | `siteEntry` | `app/site/index.html` | `APP_SITE_MISSING` / `APP_SITE_UNREADABLE` |
637
+ | `bridgeTag` | 入口页引用了 `/adep-bridge.js`(桌面壳改查 `preload.cjs`) | 桥压根不执行 ⇒ `__ADEP_APP__` 永不出现 |
638
+ | `siteAssets` | `app/site/` 三件套齐(桌面壳不走注入,跳过) | 点名缺哪一个 |
639
+ | `configDrift` | 站点内壳配置与壳根一致(比页面消费的 6 个字段;`build` 段不比) | 构建后改了配置没重建 ⇒ 页面还在打旧平台地址 |
640
+ | `buildBinding` | 壳根有 `build` 段 | 未构建过 ⇒ 提示(新 init 的正常中间态) |
641
+ | `offline` | 离线树必需文件 + 函数清单里每个函数的源码 | 点名缺件 / 缺哪个函数源码(设备上会 FN_NOT_FOUND) |
642
+ | `identity` | 桌面壳首启是否签发了 `ownerKey`、落在哪种存储(读 `data/identity/status.json`,**非机密**) | 未自举 ⇒ 提示;落在 0600 文件 ⇒ 明说「非系统凭据」;签发失败 ⇒ 原因码原样透出(APP-033) |
643
+
644
+ **它不是门**:有 `fail` 项也以退出码 0 结束(与 `adep doctor` 同口径);判定门在 `adep app build`。
645
+
646
+ #### 离线库同步(`adep app sync`,APP-032)
566
647
 
567
648
  ```bash
568
- adep app build --offline # 消费服务端 .adepack:离线白名单函数 + 基线表 + 预置资源
649
+ adep app sync --owner-key adep_ok_… # 一次往返:先上行 outbox,再拉下行增量
650
+ adep app sync --owner-key adep_ok_… --push # 只上行(排障时不必来回跑整轮)
651
+ adep app sync --owner-key adep_ok_… --pull # 只下行
652
+ ADEP_OWNER_KEY=adep_ok_… adep app sync # 也可以走环境变量
569
653
  ```
570
654
 
571
- 把设备端运行时(`@adep/app-runtime`)装入 `app/offline/`:页面、白名单云函数与数据库基线表全部**随包本地执行**,
572
- 不需要平台在线。白名单函数含**不可移植**写法时构建失败、退出码非 0,错误含违规类型与文件名行号。
573
- `--offline` 与 `--platform` 互斥——离线包与平台无关,iOS 不做运行时下发离线包。
655
+ 把桌面壳的**设备本地库**(`data/offline.sqlite`,由离线运行时首次启动时创建)与云端项目库按
656
+ 单主语义对齐:上行读本地变更流 → `outbox` → `POST /app-sync/upstream`(整批原子,服务端确认后才推进
657
+ `acked_seq`);下行 `GET /app-sync/changes?since=<游标>` → 应用进本地库(**直写驱动,不追加变更流**,
658
+ 否则刚拉下来的行会被下一次上行当成新写推回去)。
659
+
660
+ - **身份不是可选项**:`--owner-key` / `ADEP_OWNER_KEY` 必填。ownerKey 由服务端签发
661
+ (`POST /api/v1/projects/<slug>/app-installations`,移动壳由原生侧首启自举写入 Keychain / Keystore,
662
+ 桌面壳由主进程首启自举写入系统凭据库或 0600 文件,见 APP-033),
663
+ CLI **不复用平台会话**冒充设备身份;缺失即 `IDENTITY_MISSING` 且不发任何 `/app-sync` 请求。
664
+ 桌面 app 自己启动后会自动同步;本命令用于**开发期 / 排障**(比如看某次上行到底卡在哪一批)。
665
+ - 同步目标取壳配置的 `platformUrl` / `projectSlug`(不是 `ADEP_SERVER`):同步的一定是**这个壳**连的项目。
666
+ - 只支持**桌面壳**:移动壳的库在设备沙箱里,本机 CLI 摸不到(`APP_SYNC_UNSUPPORTED_SHELL`)。
667
+ - 本地库不存在 ⇒ `APP_SYNC_DB_MISSING`(先跑一次离线运行时,库才会被建出来)。
668
+ - 服务端拒绝时命令退出码非 0,**码与 `failedSeq` 原样透出**,本地位点不动(可原样重试)。
574
669
 
575
670
  ---
576
671
 
@@ -578,12 +673,13 @@ adep app build --offline # 消费服务端 .adepack:离线
578
673
 
579
674
  ### 环境变量
580
675
 
581
- | 变量 | 说明 | 缺省 |
582
- | ----------------- | --------------------------------- | -------------------------------------------- |
583
- | `ADEP_SERVER` | 平台地址(CLI 请求的默认 server) | `https://adep.top` |
584
- | `ADEP_HOME` | 凭据目录(测试隔离用) | `~/.adep` |
585
- | `ADEP_NO_BROWSER` | `1` = `adep login` 不打开浏览器 | 未设置(TTY 下自动打开) |
586
- | `ADEP_ENV` | 数据面默认环境(`dev` / `prod`) | 未设置(再读 `db_environment`,最后 `prod`) |
676
+ | 变量 | 说明 | 缺省 |
677
+ | ----------------- | --------------------------------------------------- | ----------------------------------------------------------- |
678
+ | `ADEP_SERVER` | 平台地址(CLI 请求的默认 server) | `https://adep.top` |
679
+ | `ADEP_HOME` | 凭据目录(测试隔离用) | `~/.adep` |
680
+ | `ADEP_NO_BROWSER` | `1` = `adep login` 不打开浏览器 | 未设置(TTY 下自动打开) |
681
+ | `ADEP_ENV` | 数据面默认环境(`dev` / `prod`) | 未设置(再读 `db_environment`,最后 `prod`) |
682
+ | `ADEP_OWNER_KEY` | `adep app sync` 的设备身份(服务端签发的 ownerKey) | 未设置(`--owner-key` 优先;两者都空即 `IDENTITY_MISSING`) |
587
683
 
588
684
  ```bash
589
685
  export ADEP_SERVER=https://platform.example.com