版本约束规则 / Version Constraint Rules¶
本文统一阐述 flutter_zero 体系中 项目(Project)/ CLI(fluzer)/ 模板(Template)
三者之间的版本关系,以及 create / new / gen-l10n 三条命令各自如何决定「用哪个模板、能否执行」。
背景:模板与 CLI 解耦、独立发版(见 发布流程),项目在创建时记录"出生模板版本"。 三者版本可能不一致,但 2.0.0 起已移除
minCliVersion版本门禁——CLI 力求适配所有模板版本, 仅当项目version超出命令「版本适配器」的支持范围时才报错。
三个独立发版的版本实体¶
| 实体 | 来源 | 含义 |
|---|---|---|
CLI 版本 cliVersion |
flutter_zero_cli 的 pubspec.yaml / template_config.dart 常量 |
当前运行的 fluzer 二进制版本,如 1.2.0 |
| 模板版本 | 模板注册表 template_registry.json 每条目的 version |
一个发布的模板快照,create 据此选最新、new 据此精确钉死 |
| 项目模板版本 | 项目根 fluzer.yaml(兼容 flutter_zero_config.yaml)的 version |
该项目是由哪个模板版本创建的(如 1.0.1) |
三者各自发版、互不打扰。
下文统一称:
- 「项目模板版本」 = 项目
fluzer.yaml里的version字段值(该项目"出生"时用的模板版本)。 - 「模板注册表」 = 仓库发布的
template_registry.json(templates列表,每条含version+url)。 - 「版本适配器」 = 命令内部按项目
version选择执行逻辑的对象(new→NewV1V2Adapter/NewV3Adapter,gen-l10n→GenL10nV1V2Adapter)。
⚠️
minCliVersion字段已移除:template_registry.json中残留的minCliVersion仅为历史元数据,CLI 不再读取; 配置文件fluzer.yaml中也不再含minCliVersion。旧文档/旧项目里的minCliVersion门禁逻辑均已失效。
命令如何决定「用哪个模板、能否执行」¶
create(无项目,CLI 驱动,始终用最新模板)¶
create 从零创建项目,不涉及任何 fluzer.yaml。模板选择完全由 CLI 决定:
- 在模板注册表中取
version最大者下载(始终最新模板)。 - 注册表拉取失败 / 无条目 → 静默回退内置
defaultTemplateZipUrl,不报错。
create永不拒绝——总能拉到一个可用模板。
new / gen-l10n(已有项目,按版本适配器执行)¶
new / gen-l10n 作用于已有项目,由 AdapterCommand 统一「读项目 version → 沿适配器链选认领者 → 委托执行」:
ProjectConfig.load()校验结构(version非空且>= 1.0.0下限 +template_name)。- 沿本命令的适配器链(
adapters)逐个canHandle(version),取第一个认领者。 - 命中 → 委托该适配器执行整条命令。
- 全不命中(当前 CLI 不支持该模板版本)→ 按
version >= maxSupportedVersion分支打印: - 太新:提示「请升级 fluzer」;
- 太旧:提示「请升级模板/CLI」; 并返回退出码 1。
环境变量 FLUZER_BRICKS_DIR / FLUZER_TEMPLATE_ZIP_URL 仅覆盖下载来源,不影响适配器选择。
new的适配器会按项目version精确钉死下载同名模板(selectExact);gen-l10n不下载任何模板,只在本地解析l10n.yaml/AppLocalizations并生成代码。
流程示意¶
flowchart TD
A[命令开始] --> B{作用于已有项目?}
B -- create: 无项目 --> C[取 registry 中 version 最大者下载]
C --> C1[失败/无条目 → 回退 defaultTemplateZipUrl]
B -- new / gen-l10n --> D[读项目 fluzer.yaml 的 version]
D --> E{适配器 canHandle version?}
E -- 否 --> X[报错: 版本太新请升级 CLI / 太旧请升级模板]
E -- 是 --> G{命令类型}
G -- new --> H[按 version 精确钉死下载对应 brick(feature / feature_bloc / feature_cubit)]
G -- gen-l10n --> I[本地生成 l10n 代码]
边界场景¶
| 项目模板版本(config.version) | 当前 CLI 适配器支持范围 | 结果 |
|---|---|---|
1.0.1 |
new:[1.0.0, 4.0.0)(含 NewV1V2Adapter + NewV3Adapter)/ gen-l10n:[1.0.0, ∞) |
通过;new 精确下载 1.0.1 模板(feature brick) |
2.0.0 |
new:[1.0.0, 4.0.0) / gen-l10n:[1.0.0, ∞) |
通过;new 精确下载 2.0.0 模板(feature brick) |
3.1.0 |
new:[1.0.0, 4.0.0)(NewV3Adapter 接手)/ gen-l10n:[1.0.0, ∞) |
通过;new 精确下载 3.1.0 模板,并按 --bloc/--cubit 选 feature_bloc/feature_cubit(默认 feature_bloc) |
0.9.0(低于下限 1.0.0) |
不支持 | new/gen-l10n:报错「版本太旧,请升级模板/CLI」 |
9.9.9(远超已知版本) |
当前适配器无上界,仍认领 | 通过(若未来适配器设置上界,则提示「请升级 fluzer」) |
老项目(只有旧名 flutter_zero_config.yaml) |
仍识别 | 通过;配置名向下兼容 |
维护约束(适配器与模板版本同步)¶
当模板发版引入行为差异时(例如 new 的 DI 注入锚点、目录结构随模板版本变化),
需要为其增加/调整对应的版本适配器,而非依赖 minCliVersion 门禁:
- 若新模板版本对
new/gen-l10n的执行流程有破坏性差异,新增一个覆盖该版本的适配器(如NewV2Adapter),并注册到命令的adapters链。 - 命令的
maxSupportedVersion由各适配器RangeSpec.upper推导,作为「能力上界」单一事实源。 template_registry.json的version+url是必需项(create取最大、new精确匹配);minCliVersion当前 CLI 不读取,但建议新条目继续保留,让旧版 CLI 自动跳过它撑不住的模板。