@_nazmiforreal/flutter-ota 0.1.0 → 0.1.2
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/bin/flutter-patcher.js +48 -39
- package/dart-src/packages/cli-tools/.gitkeep +0 -0
- package/dart-src/packages/cli-tools/bin/flutter_patcher.dart +9 -0
- package/dart-src/packages/cli-tools/lib/flutter_patcher_cli.dart +73 -0
- package/dart-src/packages/cli-tools/lib/src/backend.dart +162 -0
- package/dart-src/packages/cli-tools/lib/src/cli_base.dart +56 -0
- package/dart-src/packages/cli-tools/lib/src/commands/build.dart +99 -0
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +151 -0
- package/dart-src/packages/cli-tools/lib/src/commands/channel.dart +140 -0
- package/dart-src/packages/cli-tools/lib/src/commands/config_command.dart +113 -0
- package/dart-src/packages/cli-tools/lib/src/commands/console.dart +55 -0
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +95 -0
- package/dart-src/packages/cli-tools/lib/src/commands/doctor.dart +48 -0
- package/dart-src/packages/cli-tools/lib/src/commands/fingerprint.dart +29 -0
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +82 -0
- package/dart-src/packages/cli-tools/lib/src/commands/keys.dart +55 -0
- package/dart-src/packages/cli-tools/lib/src/commands/migrate.dart +132 -0
- package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +41 -0
- package/dart-src/packages/cli-tools/lib/src/config.dart +715 -0
- package/dart-src/packages/cli-tools/lib/src/operations.dart +206 -0
- package/dart-src/packages/cli-tools/lib/src/pack.dart +417 -0
- package/dart-src/packages/cli-tools/lib/src/sign.dart +60 -0
- package/dart-src/packages/cli-tools/lib/src/util.dart +86 -0
- package/dart-src/packages/cli-tools/migrations/cloudflare/0001_hot-updater_init.sql +16 -0
- package/dart-src/packages/cli-tools/migrations/cloudflare/0002_hot-updater_0.13.0.sql +8 -0
- package/dart-src/packages/cli-tools/migrations/cloudflare/0003_hot-updater_0.18.0.sql +38 -0
- package/dart-src/packages/cli-tools/migrations/cloudflare/0004_hot-updater_0.29.0.sql +11 -0
- package/dart-src/packages/cli-tools/migrations/cloudflare/0005_hot-updater_0.31.0.sql +24 -0
- package/dart-src/packages/cli-tools/migrations/cloudflare/bundles.sql +42 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20250103114225_init.sql +228 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20250314000000_hot-updater_0.13.0.sql +134 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20250516000000_hot-updater_0.18.0.sql +194 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20251014000000_hot-updater_0.21.0.sql +184 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20260401000000_hot-updater_0.29.0.sql +503 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20260414000000_hot-updater_0.30.0.sql +50 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20260422000000_hot-updater_0.31.0.sql +20 -0
- package/dart-src/packages/cli-tools/migrations/supabase/20260520014100_hot-updater_rls.sql +48 -0
- package/dart-src/packages/cli-tools/pubspec.yaml +37 -0
- package/dart-src/packages/core/lib/flutter_patcher_core.dart +29 -0
- package/dart-src/packages/core/lib/src/app_update_info.dart +111 -0
- package/dart-src/packages/core/lib/src/bundle.dart +191 -0
- package/dart-src/packages/core/lib/src/bundle_artifacts.dart +39 -0
- package/dart-src/packages/core/lib/src/bundle_patch_artifact.dart +47 -0
- package/dart-src/packages/core/lib/src/changed_asset.dart +77 -0
- package/dart-src/packages/core/lib/src/get_bundles_args.dart +78 -0
- package/dart-src/packages/core/lib/src/metadata.dart +31 -0
- package/dart-src/packages/core/lib/src/patch_info.dart +284 -0
- package/dart-src/packages/core/lib/src/platform.dart +15 -0
- package/dart-src/packages/core/lib/src/rollout.dart +209 -0
- package/dart-src/packages/core/lib/src/semver.dart +70 -0
- package/dart-src/packages/core/lib/src/semver_range.dart +358 -0
- package/dart-src/packages/core/lib/src/semver_version.dart +94 -0
- package/dart-src/packages/core/lib/src/status.dart +24 -0
- package/dart-src/packages/core/lib/src/strategy.dart +10 -0
- package/dart-src/packages/core/lib/src/update_bundle_params.dart +30 -0
- package/dart-src/packages/core/lib/src/uuid.dart +45 -0
- package/dart-src/packages/core/pubspec.yaml +9 -0
- package/dart-src/packages/core/tool/dbg.dart +6 -0
- package/dart-src/plugins/aws/.gitkeep +0 -0
- package/dart-src/plugins/aws/lib/flutter_patcher_aws.dart +12 -0
- package/dart-src/plugins/aws/lib/src/aws_cloudfront_client.dart +207 -0
- package/dart-src/plugins/aws/lib/src/aws_cloudfront_signer.dart +130 -0
- package/dart-src/plugins/aws/lib/src/aws_config.dart +59 -0
- package/dart-src/plugins/aws/lib/src/aws_database.dart +198 -0
- package/dart-src/plugins/aws/lib/src/aws_lambda_edge_storage.dart +72 -0
- package/dart-src/plugins/aws/lib/src/aws_s3_client.dart +312 -0
- package/dart-src/plugins/aws/lib/src/aws_ssm_client.dart +125 -0
- package/dart-src/plugins/aws/lib/src/aws_storage.dart +20 -0
- package/dart-src/plugins/aws/lib/src/aws_storage_profile.dart +123 -0
- package/dart-src/plugins/aws/lib/src/with_cloudfront_signed_url.dart +136 -0
- package/dart-src/plugins/aws/pubspec.yaml +22 -0
- package/dart-src/plugins/cloudflare/.gitkeep +0 -0
- package/dart-src/plugins/cloudflare/lib/flutter_patcher_cloudflare.dart +18 -0
- package/dart-src/plugins/cloudflare/lib/src/cloudflare_worker_database.dart +29 -0
- package/dart-src/plugins/cloudflare/lib/src/d1_build_where.dart +93 -0
- package/dart-src/plugins/cloudflare/lib/src/d1_bundle_mapper.dart +131 -0
- package/dart-src/plugins/cloudflare/lib/src/d1_client.dart +66 -0
- package/dart-src/plugins/cloudflare/lib/src/d1_config.dart +30 -0
- package/dart-src/plugins/cloudflare/lib/src/d1_database.dart +16 -0
- package/dart-src/plugins/cloudflare/lib/src/d1_database_plugin.dart +314 -0
- package/dart-src/plugins/cloudflare/lib/src/r2_config.dart +50 -0
- package/dart-src/plugins/cloudflare/lib/src/r2_s3_client.dart +287 -0
- package/dart-src/plugins/cloudflare/lib/src/r2_storage.dart +23 -0
- package/dart-src/plugins/cloudflare/lib/src/r2_storage_profile.dart +110 -0
- package/dart-src/plugins/cloudflare/migrations/0001_hot-updater_init.sql +16 -0
- package/dart-src/plugins/cloudflare/migrations/0002_hot-updater_0.13.0.sql +8 -0
- package/dart-src/plugins/cloudflare/migrations/0003_hot-updater_0.18.0.sql +38 -0
- package/dart-src/plugins/cloudflare/migrations/0004_hot-updater_0.29.0.sql +11 -0
- package/dart-src/plugins/cloudflare/migrations/0005_hot-updater_0.31.0.sql +24 -0
- package/dart-src/plugins/cloudflare/pubspec.yaml +20 -0
- package/dart-src/plugins/cloudflare/sql/bundles.sql +42 -0
- package/dart-src/plugins/plugin-core/lib/flutter_patcher_plugin_core.dart +42 -0
- package/dart-src/plugins/plugin-core/lib/src/asset_storage_layout.dart +94 -0
- package/dart-src/plugins/plugin-core/lib/src/bundle_storage_layout.dart +44 -0
- package/dart-src/plugins/plugin-core/lib/src/bundle_unit_of_work.dart +259 -0
- package/dart-src/plugins/plugin-core/lib/src/bundle_unit_of_work_store.dart +20 -0
- package/dart-src/plugins/plugin-core/lib/src/calculate_pagination.dart +29 -0
- package/dart-src/plugins/plugin-core/lib/src/compression_format.dart +63 -0
- package/dart-src/plugins/plugin-core/lib/src/content_addressed_assets.dart +22 -0
- package/dart-src/plugins/plugin-core/lib/src/create_blob_database_plugin.dart +853 -0
- package/dart-src/plugins/plugin-core/lib/src/create_database_plugin.dart +525 -0
- package/dart-src/plugins/plugin-core/lib/src/create_storage_key_builder.dart +15 -0
- package/dart-src/plugins/plugin-core/lib/src/create_storage_plugin.dart +130 -0
- package/dart-src/plugins/plugin-core/lib/src/filter_compatible_app_versions.dart +18 -0
- package/dart-src/plugins/plugin-core/lib/src/generate_min_bundle_id.dart +19 -0
- package/dart-src/plugins/plugin-core/lib/src/get_update_info.dart +241 -0
- package/dart-src/plugins/plugin-core/lib/src/is_object.dart +5 -0
- package/dart-src/plugins/plugin-core/lib/src/legacy_asset_storage_layout.dart +9 -0
- package/dart-src/plugins/plugin-core/lib/src/paginate_bundles.dart +112 -0
- package/dart-src/plugins/plugin-core/lib/src/parse_storage_uri.dart +44 -0
- package/dart-src/plugins/plugin-core/lib/src/query_bundles.dart +70 -0
- package/dart-src/plugins/plugin-core/lib/src/request_update_bundle_state.dart +62 -0
- package/dart-src/plugins/plugin-core/lib/src/resolve_update_info_from_bundles.dart +43 -0
- package/dart-src/plugins/plugin-core/lib/src/storage_profile.dart +27 -0
- package/dart-src/plugins/plugin-core/lib/src/types.dart +454 -0
- package/dart-src/plugins/plugin-core/lib/src/uuidv7.dart +41 -0
- package/dart-src/plugins/plugin-core/pubspec.yaml +15 -0
- package/dart-src/plugins/postgres/.gitkeep +0 -0
- package/dart-src/plugins/postgres/lib/flutter_patcher_postgres.dart +17 -0
- package/dart-src/plugins/postgres/lib/src/postgres_bundle_mapper.dart +130 -0
- package/dart-src/plugins/postgres/lib/src/postgres_client.dart +90 -0
- package/dart-src/plugins/postgres/lib/src/postgres_config.dart +35 -0
- package/dart-src/plugins/postgres/lib/src/postgres_database.dart +302 -0
- package/dart-src/plugins/postgres/lib/src/postgres_get_update_info.dart +120 -0
- package/dart-src/plugins/postgres/lib/src/postgres_storage.dart +205 -0
- package/dart-src/plugins/postgres/lib/src/postgres_types.dart +132 -0
- package/dart-src/plugins/postgres/pubspec.yaml +18 -0
- package/dart-src/plugins/postgres/sql/bundles.sql +45 -0
- package/dart-src/plugins/postgres/sql/get_target_app_version_list.sql +21 -0
- package/dart-src/plugins/postgres/sql/get_update_info.spec.ts +171 -0
- package/dart-src/plugins/postgres/sql/get_update_info_by_app_version.sql +126 -0
- package/dart-src/plugins/postgres/sql/get_update_info_by_fingerprint_hash.sql +125 -0
- package/dart-src/plugins/postgres/sql/hash_user_id.sql +30 -0
- package/dart-src/plugins/postgres/sql/is_device_eligible.sql +237 -0
- package/dart-src/plugins/postgres/sql/prepareSql.ts +11 -0
- package/dart-src/plugins/standalone/.gitkeep +0 -0
- package/dart-src/plugins/standalone/lib/flutter_patcher_standalone.dart +12 -0
- package/dart-src/plugins/standalone/lib/src/standalone_config.dart +107 -0
- package/dart-src/plugins/standalone/lib/src/standalone_database.dart +233 -0
- package/dart-src/plugins/standalone/lib/src/standalone_storage.dart +175 -0
- package/dart-src/plugins/standalone/pubspec.yaml +18 -0
- package/dart-src/plugins/supabase/lib/edge.dart +10 -0
- package/dart-src/plugins/supabase/lib/flutter_patcher_supabase.dart +21 -0
- package/dart-src/plugins/supabase/lib/src/supabase_bundle_mapper.dart +129 -0
- package/dart-src/plugins/supabase/lib/src/supabase_client_adapter.dart +154 -0
- package/dart-src/plugins/supabase/lib/src/supabase_client_http.dart +516 -0
- package/dart-src/plugins/supabase/lib/src/supabase_config.dart +34 -0
- package/dart-src/plugins/supabase/lib/src/supabase_database.dart +422 -0
- package/dart-src/plugins/supabase/lib/src/supabase_edge_function_database.dart +32 -0
- package/dart-src/plugins/supabase/lib/src/supabase_edge_function_storage.dart +99 -0
- package/dart-src/plugins/supabase/lib/src/supabase_signed_url_batcher.dart +145 -0
- package/dart-src/plugins/supabase/lib/src/supabase_storage.dart +298 -0
- package/dart-src/plugins/supabase/lib/src/types.dart +130 -0
- package/dart-src/plugins/supabase/pubspec.yaml +19 -0
- package/dart-src/plugins/supabase/supabase/edge-functions/index.ts +44 -0
- package/dart-src/plugins/supabase/supabase/edge-functions/runtime.docker.integration.spec.ts +968 -0
- package/dart-src/plugins/supabase/supabase/migrations/20250103114225_init.sql +228 -0
- package/dart-src/plugins/supabase/supabase/migrations/20250314000000_hot-updater_0.13.0.sql +134 -0
- package/dart-src/plugins/supabase/supabase/migrations/20250516000000_hot-updater_0.18.0.sql +194 -0
- package/dart-src/plugins/supabase/supabase/migrations/20251014000000_hot-updater_0.21.0.sql +184 -0
- package/dart-src/plugins/supabase/supabase/migrations/20260401000000_hot-updater_0.29.0.sql +503 -0
- package/dart-src/plugins/supabase/supabase/migrations/20260414000000_hot-updater_0.30.0.sql +50 -0
- package/dart-src/plugins/supabase/supabase/migrations/20260422000000_hot-updater_0.31.0.sql +20 -0
- package/dart-src/plugins/supabase/supabase/migrations/20260520014100_hot-updater_rls.sql +48 -0
- package/package.json +2 -1
- package/scripts/postinstall.js +53 -25
- /package/bin/{flutter-patcher-linux → flutter-patcher-linux-x64} +0 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/// SemVer range evaluation following node-semver semantics (as verkit).
|
|
2
|
+
///
|
|
3
|
+
/// A range is `||`-separated comparator sets; each set is space-separated
|
|
4
|
+
/// AND-ed comparators. Shorthand (~, ^, x-ranges, partials, hyphen ranges)
|
|
5
|
+
/// is expanded into primitive comparators.
|
|
6
|
+
library;
|
|
7
|
+
|
|
8
|
+
import 'semver_version.dart';
|
|
9
|
+
|
|
10
|
+
enum _Op { lt, lte, gt, gte, eq }
|
|
11
|
+
|
|
12
|
+
class _Comparator {
|
|
13
|
+
final _Op op;
|
|
14
|
+
final SemVer version;
|
|
15
|
+
const _Comparator(this.op, this.version);
|
|
16
|
+
|
|
17
|
+
bool test(SemVer v) {
|
|
18
|
+
switch (op) {
|
|
19
|
+
case _Op.lt:
|
|
20
|
+
return v < version;
|
|
21
|
+
case _Op.lte:
|
|
22
|
+
return v <= version;
|
|
23
|
+
case _Op.gt:
|
|
24
|
+
return v > version;
|
|
25
|
+
case _Op.gte:
|
|
26
|
+
return v >= version;
|
|
27
|
+
case _Op.eq:
|
|
28
|
+
// Build metadata ignored for equality of ranges.
|
|
29
|
+
return v.major == version.major &&
|
|
30
|
+
v.minor == version.minor &&
|
|
31
|
+
v.patch == version.patch &&
|
|
32
|
+
v.prerelease.join('.') == version.prerelease.join('.');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Whether this comparator explicitly opts a version into prerelease
|
|
37
|
+
/// testing: same major.minor.patch tuple with its own prerelease set.
|
|
38
|
+
bool allowsPrereleaseOf(SemVer v) =>
|
|
39
|
+
version.isPrerelease &&
|
|
40
|
+
version.major == v.major &&
|
|
41
|
+
version.minor == v.minor &&
|
|
42
|
+
version.patch == v.patch;
|
|
43
|
+
|
|
44
|
+
@override
|
|
45
|
+
String toString() => '${_opStr(op)}$version';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
String _opStr(_Op o) => switch (o) {
|
|
49
|
+
_Op.lt => '<',
|
|
50
|
+
_Op.lte => '<=',
|
|
51
|
+
_Op.gt => '>',
|
|
52
|
+
_Op.gte => '>=',
|
|
53
|
+
_Op.eq => '=',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
final RegExp _xRe = RegExp(r'^[xX*]$');
|
|
57
|
+
|
|
58
|
+
bool _isX(String? s) => s == null || s.isEmpty || _xRe.hasMatch(s);
|
|
59
|
+
|
|
60
|
+
/// Expands one raw comparator token into primitives.
|
|
61
|
+
List<_Comparator> _parseToken(String raw) {
|
|
62
|
+
var t = raw.trim();
|
|
63
|
+
if (t.isEmpty || t == '*' || t == 'x' || t == 'X') return const [];
|
|
64
|
+
|
|
65
|
+
// Strip operator prefix.
|
|
66
|
+
String op;
|
|
67
|
+
if (t.startsWith('>=')) {
|
|
68
|
+
op = '>=';
|
|
69
|
+
t = t.substring(2);
|
|
70
|
+
} else if (t.startsWith('<=')) {
|
|
71
|
+
op = '<=';
|
|
72
|
+
t = t.substring(2);
|
|
73
|
+
} else if (t.startsWith('>')) {
|
|
74
|
+
op = '>';
|
|
75
|
+
t = t.substring(1);
|
|
76
|
+
} else if (t.startsWith('<')) {
|
|
77
|
+
op = '<';
|
|
78
|
+
t = t.substring(1);
|
|
79
|
+
} else if (t.startsWith('~')) {
|
|
80
|
+
op = '~';
|
|
81
|
+
t = t.substring(1);
|
|
82
|
+
} else if (t.startsWith('^')) {
|
|
83
|
+
op = '^';
|
|
84
|
+
t = t.substring(1);
|
|
85
|
+
} else {
|
|
86
|
+
if (t.startsWith('=')) t = t.substring(1);
|
|
87
|
+
op = '';
|
|
88
|
+
}
|
|
89
|
+
t = t.trim();
|
|
90
|
+
|
|
91
|
+
final m = RegExp(
|
|
92
|
+
r'^v?(\d+|x|X|\*)(?:\.(\d+|x|X|\*))?(?:\.(\d+|x|X|\*))?'
|
|
93
|
+
r'(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?'
|
|
94
|
+
r'(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$',
|
|
95
|
+
).firstMatch(t);
|
|
96
|
+
if (m == null) throw FormatException('invalid comparator: $raw');
|
|
97
|
+
|
|
98
|
+
final majS = m.group(1)!;
|
|
99
|
+
final minS = m.group(2);
|
|
100
|
+
final patS = m.group(3);
|
|
101
|
+
final preRaw = m.group(4);
|
|
102
|
+
|
|
103
|
+
final majIsX = _isX(majS);
|
|
104
|
+
final minIsX = !majIsX && _isX(minS);
|
|
105
|
+
final patIsX = !(majIsX || minIsX) && _isX(patS);
|
|
106
|
+
final hasPre = preRaw != null && preRaw.isNotEmpty;
|
|
107
|
+
|
|
108
|
+
SemVer ver(String a, String b, String c, [List<String> pre = const []]) =>
|
|
109
|
+
SemVer(int.parse(a), int.parse(b), int.parse(c), pre);
|
|
110
|
+
|
|
111
|
+
// Full X handling per node-semver replaceXRanges rules.
|
|
112
|
+
if (majIsX) {
|
|
113
|
+
return const [_Comparator(_Op.gte, SemVer(0, 0, 0))];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
final hasMinor = !minIsX;
|
|
117
|
+
final hasPatch = hasMinor && !patIsX;
|
|
118
|
+
|
|
119
|
+
switch (op) {
|
|
120
|
+
case '':
|
|
121
|
+
case '=':
|
|
122
|
+
if (!hasMinor) {
|
|
123
|
+
return [
|
|
124
|
+
_Comparator(_Op.gte, ver(majS, '0', '0')),
|
|
125
|
+
_Comparator(_Op.lt, ver('${int.parse(majS) + 1}', '0', '0')),
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
if (!hasPatch) {
|
|
129
|
+
return [
|
|
130
|
+
_Comparator(_Op.gte, ver(majS, minS!, '0')),
|
|
131
|
+
_Comparator(_Op.lt, ver(majS, '${int.parse(minS) + 1}', '0')),
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
final pre =
|
|
135
|
+
hasPre ? preRaw.split('.') : const <String>[];
|
|
136
|
+
return [_Comparator(_Op.eq, ver(majS, minS!, patS!, pre))];
|
|
137
|
+
|
|
138
|
+
case '>':
|
|
139
|
+
if (!hasMinor) {
|
|
140
|
+
return [_Comparator(_Op.gte, ver('${int.parse(majS) + 1}', '0', '0'))];
|
|
141
|
+
}
|
|
142
|
+
if (!hasPatch) {
|
|
143
|
+
return [
|
|
144
|
+
_Comparator(_Op.gte, ver(majS, '${int.parse(minS!) + 1}', '0'))
|
|
145
|
+
];
|
|
146
|
+
}
|
|
147
|
+
return [_Comparator(_Op.gt, ver(majS, minS!, patS!))];
|
|
148
|
+
|
|
149
|
+
case '>=':
|
|
150
|
+
if (!hasMinor) {
|
|
151
|
+
return [_Comparator(_Op.gte, ver(majS, '0', '0'))];
|
|
152
|
+
}
|
|
153
|
+
if (!hasPatch) {
|
|
154
|
+
return [_Comparator(_Op.gte, ver(majS, minS!, '0'))];
|
|
155
|
+
}
|
|
156
|
+
return [
|
|
157
|
+
_Comparator(_Op.gte, ver(majS, minS!, patS!,
|
|
158
|
+
hasPre ? preRaw.split('.') : const []))
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
case '<':
|
|
162
|
+
if (!hasMinor) {
|
|
163
|
+
return [_Comparator(_Op.lt, ver(majS, '0', '0'))];
|
|
164
|
+
}
|
|
165
|
+
if (!hasPatch) {
|
|
166
|
+
return [_Comparator(_Op.lt, ver(majS, minS!, '0'))];
|
|
167
|
+
}
|
|
168
|
+
return [
|
|
169
|
+
_Comparator(
|
|
170
|
+
_Op.lt,
|
|
171
|
+
ver(majS, minS!, patS!,
|
|
172
|
+
hasPre ? preRaw.split('.') : const []))
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
case '<=':
|
|
176
|
+
if (!hasMinor) {
|
|
177
|
+
// <=* handled above; here <=N means < N+1.0.0
|
|
178
|
+
return [_Comparator(_Op.lt, ver('${int.parse(majS) + 1}', '0', '0'))];
|
|
179
|
+
}
|
|
180
|
+
if (!hasPatch) {
|
|
181
|
+
return [
|
|
182
|
+
_Comparator(_Op.lt, ver(majS, '${int.parse(minS!) + 1}', '0'))
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
return [
|
|
186
|
+
_Comparator(_Op.lte, ver(majS, minS!, patS!,
|
|
187
|
+
hasPre ? preRaw.split('.') : const []))
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
case '~':
|
|
191
|
+
if (!hasMinor) {
|
|
192
|
+
return [
|
|
193
|
+
_Comparator(_Op.gte, ver(majS, '0', '0')),
|
|
194
|
+
_Comparator(_Op.lt, ver('${int.parse(majS) + 1}', '0', '0')),
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
if (!hasPatch) {
|
|
198
|
+
return [
|
|
199
|
+
_Comparator(_Op.gte, ver(majS, minS!, '0')),
|
|
200
|
+
_Comparator(_Op.lt, ver(majS, '${int.parse(minS) + 1}', '0')),
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
return [
|
|
204
|
+
_Comparator(
|
|
205
|
+
_Op.gte,
|
|
206
|
+
ver(majS, minS!, patS!,
|
|
207
|
+
hasPre ? preRaw.split('.') : const [])),
|
|
208
|
+
_Comparator(_Op.lt, ver(majS, '${int.parse(minS) + 1}', '0')),
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
case '^':
|
|
212
|
+
if (!hasMinor) {
|
|
213
|
+
return [
|
|
214
|
+
_Comparator(_Op.gte, ver(majS, '0', '0')),
|
|
215
|
+
_Comparator(_Op.lt, ver('${int.parse(majS) + 1}', '0', '0')),
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
if (!hasPatch) {
|
|
219
|
+
if (int.parse(majS) == 0) {
|
|
220
|
+
return [
|
|
221
|
+
_Comparator(_Op.gte, ver('0', minS!, '0')),
|
|
222
|
+
_Comparator(_Op.lt, ver('0', '${int.parse(minS) + 1}', '0')),
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
return [
|
|
226
|
+
_Comparator(_Op.gte, ver(majS, minS!, '0')),
|
|
227
|
+
_Comparator(_Op.lt, ver('${int.parse(majS) + 1}', '0', '0')),
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
final maj = int.parse(majS);
|
|
231
|
+
final min = int.parse(minS!);
|
|
232
|
+
final pat = int.parse(patS!);
|
|
233
|
+
final upper = maj > 0
|
|
234
|
+
? SemVer(maj + 1, 0, 0)
|
|
235
|
+
: (min > 0 ? SemVer(0, min + 1, 0) : SemVer(0, 0, pat + 1));
|
|
236
|
+
return [
|
|
237
|
+
_Comparator(_Op.gte,
|
|
238
|
+
ver(majS, minS, patS, hasPre ? preRaw.split('.') : const [])),
|
|
239
|
+
_Comparator(_Op.lt, upper),
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
throw StateError('unreachable');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// Splits a comparator set string into individual comparator tokens,
|
|
246
|
+
/// correctly joining operator prefixes (`>=`, `<=`, `>`, `<`, `~`, `^`, `=`)
|
|
247
|
+
/// with their following version string even when separated by whitespace.
|
|
248
|
+
///
|
|
249
|
+
/// For example, `>= 5.7.0 <= 5.7.4` → `['>= 5.7.0', '<= 5.7.4']`.
|
|
250
|
+
List<String> _splitComparators(String set) {
|
|
251
|
+
final tokens = <String>[];
|
|
252
|
+
// Match operator-prefixed comparators first (e.g., ">= 5.7.0"), then bare tokens.
|
|
253
|
+
final re = RegExp(r'(?:>=|<=|>|<|~|\^|=)\s*\S+|\S+');
|
|
254
|
+
for (final m in re.allMatches(set)) {
|
|
255
|
+
tokens.add(m.group(0)!.trim());
|
|
256
|
+
}
|
|
257
|
+
return tokens;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
List<List<_Comparator>> _parseRange(String range) {
|
|
261
|
+
final sets = range.trim().split(r'||');
|
|
262
|
+
final result = <List<_Comparator>>[];
|
|
263
|
+
for (var set in sets.map((s) => s.trim()).toList()) {
|
|
264
|
+
if (set.isEmpty) set = '*';
|
|
265
|
+
// Hyphen ranges first.
|
|
266
|
+
final hyphenMatch = RegExp(
|
|
267
|
+
r'^\s*(\S+)\s+-\s+(\S+)\s*$')
|
|
268
|
+
.firstMatch(set);
|
|
269
|
+
if (hyphenMatch != null) {
|
|
270
|
+
final comps = _hyphenToComparators(hyphenMatch.group(1)!,
|
|
271
|
+
hyphenMatch.group(2)!);
|
|
272
|
+
result.add(comps);
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
final comparators = <_Comparator>[];
|
|
276
|
+
for (final token in _splitComparators(set)) {
|
|
277
|
+
comparators.addAll(_parseToken(token));
|
|
278
|
+
}
|
|
279
|
+
result.add(comparators);
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
List<_Comparator> _hyphenToComparators(String leftRaw, String rightRaw) {
|
|
285
|
+
final out = <_Comparator>[];
|
|
286
|
+
final fullRe = RegExp(
|
|
287
|
+
r'^v?(\d+|x|X|\*)(?:\.(\d+|x|X|\*))?(?:\.(\d+|x|X|\*))?'
|
|
288
|
+
r'(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?'
|
|
289
|
+
r'(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$',
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
// Left side: full version (with optional prerelease) -> inclusive lower.
|
|
293
|
+
final lm = fullRe.firstMatch(leftRaw.trim());
|
|
294
|
+
if (lm != null) {
|
|
295
|
+
final maj = lm.group(1)!;
|
|
296
|
+
final min = lm.group(2);
|
|
297
|
+
final pat = lm.group(3);
|
|
298
|
+
final pre = lm.group(4)?.split('.') ?? const <String>[];
|
|
299
|
+
if (_isX(min)) {
|
|
300
|
+
out.add(_Comparator(_Op.gte, SemVer(int.parse(maj), 0, 0)));
|
|
301
|
+
} else if (_isX(pat)) {
|
|
302
|
+
out.add(
|
|
303
|
+
_Comparator(_Op.gte, SemVer(int.parse(maj), int.parse(min!), 0)));
|
|
304
|
+
} else {
|
|
305
|
+
out.add(_Comparator(_Op.gte,
|
|
306
|
+
SemVer(int.parse(maj), int.parse(min!), int.parse(pat!), pre)));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Right side: partial -> exclusive upper bound at next boundary;
|
|
311
|
+
// full version -> inclusive upper.
|
|
312
|
+
final rm = fullRe.firstMatch(rightRaw.trim());
|
|
313
|
+
if (rm != null) {
|
|
314
|
+
final maj = rm.group(1)!;
|
|
315
|
+
final min = rm.group(2);
|
|
316
|
+
final pat = rm.group(3);
|
|
317
|
+
final pre = rm.group(4)?.split('.') ?? const <String>[];
|
|
318
|
+
if (_isX(min)) {
|
|
319
|
+
out.add(_Comparator(_Op.lt, SemVer(int.parse(maj) + 1, 0, 0)));
|
|
320
|
+
} else if (_isX(pat)) {
|
|
321
|
+
out.add(_Comparator(
|
|
322
|
+
_Op.lt, SemVer(int.parse(maj), int.parse(min!) + 1, 0)));
|
|
323
|
+
} else {
|
|
324
|
+
out.add(_Comparator(_Op.lte,
|
|
325
|
+
SemVer(int.parse(maj), int.parse(min!), int.parse(pat!), pre)));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return out;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/// node-semver `satisfies(version, range)` with default options:
|
|
332
|
+
/// prerelease versions only match when some comparator in the matched set
|
|
333
|
+
/// carries the same major.minor.patch tuple WITH a prerelease.
|
|
334
|
+
bool satisfies(SemVer version, String range) {
|
|
335
|
+
List<List<_Comparator>> sets;
|
|
336
|
+
try {
|
|
337
|
+
sets = _parseRange(range);
|
|
338
|
+
} on FormatException {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
for (final set in sets) {
|
|
342
|
+
var ok = true;
|
|
343
|
+
for (final c in set) {
|
|
344
|
+
if (!c.test(version)) {
|
|
345
|
+
ok = false;
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
if (!ok) continue;
|
|
350
|
+
if (version.isPrerelease) {
|
|
351
|
+
final allowed =
|
|
352
|
+
set.any((c) => c.allowsPrereleaseOf(version));
|
|
353
|
+
if (!allowed) continue;
|
|
354
|
+
}
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/// SemVer version parsing/comparison following the node-semver conventions
|
|
2
|
+
/// that verkit (hot-updater's semver dependency) implements.
|
|
3
|
+
library;
|
|
4
|
+
|
|
5
|
+
class SemVer implements Comparable<SemVer> {
|
|
6
|
+
final int major;
|
|
7
|
+
final int minor;
|
|
8
|
+
final int patch;
|
|
9
|
+
final List<String> prerelease; // identifiers; numeric ones stay numeric-ish
|
|
10
|
+
final String? build;
|
|
11
|
+
|
|
12
|
+
const SemVer(
|
|
13
|
+
this.major,
|
|
14
|
+
this.minor,
|
|
15
|
+
this.patch, [
|
|
16
|
+
this.prerelease = const [],
|
|
17
|
+
this.build,
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
/// Strict-ish parse; allows partials ("1", "1.2") padded with zeros.
|
|
21
|
+
/// Returns null on failure.
|
|
22
|
+
static SemVer? tryParse(String input) {
|
|
23
|
+
var s = input.trim();
|
|
24
|
+
if (s.isEmpty) return null;
|
|
25
|
+
final m = RegExp(
|
|
26
|
+
r'^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?'
|
|
27
|
+
r'(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?'
|
|
28
|
+
r'(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$',
|
|
29
|
+
).firstMatch(s);
|
|
30
|
+
if (m == null) return null;
|
|
31
|
+
return SemVer(
|
|
32
|
+
int.parse(m.group(1)!),
|
|
33
|
+
int.tryParse(m.group(2) ?? '') ?? 0,
|
|
34
|
+
int.tryParse(m.group(3) ?? '') ?? 0,
|
|
35
|
+
m.group(4)?.split('.') ?? const [],
|
|
36
|
+
m.group(5),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
factory SemVer.fromJson(Map<String, dynamic> j) => SemVer(
|
|
41
|
+
j['major'] as int,
|
|
42
|
+
j['minor'] as int,
|
|
43
|
+
j['patch'] as int,
|
|
44
|
+
(j['prerelease'] as List?)?.map((e) => '$e').toList() ?? const [],
|
|
45
|
+
j['build'] as String?,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
bool get isPrerelease => prerelease.isNotEmpty;
|
|
49
|
+
|
|
50
|
+
@override
|
|
51
|
+
String toString() => '$major.$minor.$patch'
|
|
52
|
+
'${prerelease.isEmpty ? '' : '-${prerelease.join('.')}'}'
|
|
53
|
+
'${build == null ? '' : '+$build'}';
|
|
54
|
+
|
|
55
|
+
@override
|
|
56
|
+
int compareTo(SemVer o) {
|
|
57
|
+
final main = [major, minor, patch];
|
|
58
|
+
final other = [o.major, o.minor, o.patch];
|
|
59
|
+
for (var i = 0; i < 3; i++) {
|
|
60
|
+
final c = main[i].compareTo(other[i]);
|
|
61
|
+
if (c != 0) return c;
|
|
62
|
+
}
|
|
63
|
+
// Empty prerelease set > non-empty.
|
|
64
|
+
if (prerelease.isEmpty && o.prerelease.isEmpty) return 0;
|
|
65
|
+
if (prerelease.isEmpty) return 1;
|
|
66
|
+
if (o.prerelease.isEmpty) return -1;
|
|
67
|
+
for (var i = 0; i < prerelease.length && i < o.prerelease.length; i++) {
|
|
68
|
+
final c = _compareIdentifier(prerelease[i], o.prerelease[i]);
|
|
69
|
+
if (c != 0) return c;
|
|
70
|
+
}
|
|
71
|
+
return prerelease.length.compareTo(o.prerelease.length);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static int _compareIdentifier(String a, String b) {
|
|
75
|
+
final na = int.tryParse(a);
|
|
76
|
+
final nb = int.tryParse(b);
|
|
77
|
+
if (na != null && nb != null) return na.compareTo(nb);
|
|
78
|
+
if (na != null) return -1; // numeric < alphanumeric
|
|
79
|
+
if (nb != null) return 1;
|
|
80
|
+
return a.compareTo(b);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@override
|
|
84
|
+
bool operator ==(Object o) =>
|
|
85
|
+
o is SemVer && compareTo(o) == 0 && o.build == build;
|
|
86
|
+
|
|
87
|
+
@override
|
|
88
|
+
int get hashCode => Object.hash(major, minor, patch, prerelease);
|
|
89
|
+
|
|
90
|
+
bool operator <(SemVer o) => compareTo(o) < 0;
|
|
91
|
+
bool operator >(SemVer o) => compareTo(o) > 0;
|
|
92
|
+
bool operator <=(SemVer o) => compareTo(o) <= 0;
|
|
93
|
+
bool operator >=(SemVer o) => compareTo(o) >= 0;
|
|
94
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// Update status enums — hot-updater `UpdateStatus` / `AppUpdateStatus`.
|
|
2
|
+
library;
|
|
3
|
+
|
|
4
|
+
enum UpdateStatus {
|
|
5
|
+
rollback('ROLLBACK'),
|
|
6
|
+
update('UPDATE');
|
|
7
|
+
|
|
8
|
+
final String value;
|
|
9
|
+
const UpdateStatus(this.value);
|
|
10
|
+
|
|
11
|
+
static UpdateStatus fromValue(String v) => UpdateStatus.values
|
|
12
|
+
.firstWhere((s) => s.value == v,
|
|
13
|
+
orElse: () => throw ArgumentError('unknown status: $v'));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// What the client derives: UP_TO_DATE | ROLLBACK | UPDATE.
|
|
17
|
+
enum AppUpdateStatus {
|
|
18
|
+
upToDate('UP_TO_DATE'),
|
|
19
|
+
rollback('ROLLBACK'),
|
|
20
|
+
update('UPDATE');
|
|
21
|
+
|
|
22
|
+
final String value;
|
|
23
|
+
const AppUpdateStatus(this.value);
|
|
24
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import 'platform.dart';
|
|
2
|
+
|
|
3
|
+
/// hot-updater `UpdateBundleParams` — device-side parameters sent with
|
|
4
|
+
/// update requests.
|
|
5
|
+
class UpdateBundleParams {
|
|
6
|
+
final Platform platform;
|
|
7
|
+
final String bundleId;
|
|
8
|
+
final String minBundleId;
|
|
9
|
+
final String channel;
|
|
10
|
+
final String appVersion;
|
|
11
|
+
final String? fingerprintHash;
|
|
12
|
+
|
|
13
|
+
const UpdateBundleParams({
|
|
14
|
+
required this.platform,
|
|
15
|
+
required this.bundleId,
|
|
16
|
+
required this.minBundleId,
|
|
17
|
+
required this.channel,
|
|
18
|
+
required this.appVersion,
|
|
19
|
+
required this.fingerprintHash,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
Map<String, dynamic> toJson() => {
|
|
23
|
+
'platform': platform.value,
|
|
24
|
+
'bundleId': bundleId,
|
|
25
|
+
'minBundleId': minBundleId,
|
|
26
|
+
'channel': channel,
|
|
27
|
+
'appVersion': appVersion,
|
|
28
|
+
if (fingerprintHash != null) 'fingerprintHash': fingerprintHash,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// UUID helpers matching hot-updater semantics.
|
|
2
|
+
///
|
|
3
|
+
/// Bundle ids are UUIDv7 (time-sortable); hot-updater relies on lexicographic
|
|
4
|
+
/// ordering of the string form matching chronological order.
|
|
5
|
+
library;
|
|
6
|
+
|
|
7
|
+
import 'dart:math';
|
|
8
|
+
|
|
9
|
+
const String nilUuid = '00000000-0000-0000-0000-000000000000';
|
|
10
|
+
|
|
11
|
+
final RegExp _uuidV7Pattern = RegExp(
|
|
12
|
+
r'^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$',
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
final Random _random = Random.secure();
|
|
16
|
+
|
|
17
|
+
String _hex(int value, int width) =>
|
|
18
|
+
value.toRadixString(16).padLeft(width, '0');
|
|
19
|
+
|
|
20
|
+
/// Generates a lowercase RFC 9562 UUIDv7 string (unix-ms timestamp based).
|
|
21
|
+
String uuidV7({DateTime? now}) {
|
|
22
|
+
final ts = (now ?? DateTime.now()).millisecondsSinceEpoch;
|
|
23
|
+
if (ts < 0 || ts > 0xFFFFFFFFFFFF) {
|
|
24
|
+
throw ArgumentError('timestamp out of UUIDv7 range');
|
|
25
|
+
}
|
|
26
|
+
// Layout: 48-bit ts | ver(0101)+12 rand bits | var(10)+62 rand bits.
|
|
27
|
+
// Groups: 8 - 4 - "7"+3 - 2(var)+2 - 12.
|
|
28
|
+
final rand = List.generate(10, (_) => _random.nextInt(256));
|
|
29
|
+
final tsHex = _hex(ts, 12);
|
|
30
|
+
final g3 = '${_hex(rand[0] & 0x0F, 1)}${_hex(rand[1], 2)}';
|
|
31
|
+
final g4 =
|
|
32
|
+
'${_hex((rand[2] & 0x3F) | 0x80, 2)}${_hex(rand[3], 2)}';
|
|
33
|
+
final g5 = StringBuffer();
|
|
34
|
+
for (var i = 4; i < 10; i++) {
|
|
35
|
+
g5.write(_hex(rand[i], 2));
|
|
36
|
+
}
|
|
37
|
+
return '${tsHex.substring(0, 8)}-'
|
|
38
|
+
'${tsHex.substring(8, 12)}-'
|
|
39
|
+
'7$g3-$g4-$g5';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
bool isUuidV7(String value) => _uuidV7Pattern.hasMatch(value);
|
|
43
|
+
|
|
44
|
+
/// Lexicographic comparison used by hot-updater for bundle ordering.
|
|
45
|
+
int compareBundleIds(String a, String b) => a.compareTo(b);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
name: flutter_patcher_core
|
|
2
|
+
description: Core data model, rollout cohorts, and shared utilities for flutter_patcher — Dart translation of hot-updater's packages/core.
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
publish_to: none
|
|
5
|
+
|
|
6
|
+
environment:
|
|
7
|
+
sdk: '>=3.0.0 <4.0.0'
|
|
8
|
+
dev_dependencies:
|
|
9
|
+
test: ^1.31.2
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export 'src/aws_storage.dart' show s3Storage;
|
|
2
|
+
export 'src/aws_database.dart'
|
|
3
|
+
show S3DatabaseConfig, s3Database, defaultAwsS3DatabaseClientFactory, defaultAwsCloudFrontClientFactory;
|
|
4
|
+
export 'src/aws_config.dart' show AwsS3StorageConfig, defaultAwsS3ClientFactory;
|
|
5
|
+
export 'src/aws_s3_client.dart' show AwsS3ClientLike;
|
|
6
|
+
export 'src/aws_cloudfront_client.dart' show AwsCloudFrontClientLike;
|
|
7
|
+
export 'src/aws_cloudfront_signer.dart'
|
|
8
|
+
show cloudfrontSignedUrl, verifyCloudfrontSignedUrl;
|
|
9
|
+
export 'src/with_cloudfront_signed_url.dart'
|
|
10
|
+
show WithCloudFrontSignedUrlOptions, withCloudFrontSignedUrl;
|
|
11
|
+
export 'src/aws_lambda_edge_storage.dart'
|
|
12
|
+
show AwsLambdaEdgeStorageConfig, awsLambdaEdgeStorage, s3LambdaEdgeStorage;
|