native-update 1.3.0 → 1.3.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.
Files changed (66) hide show
  1. package/Readme.md +5 -5
  2. package/cli/index.js +5 -6
  3. package/cli/node_modules/.yarn-integrity +16 -0
  4. package/cli/node_modules/commander/LICENSE +22 -0
  5. package/cli/node_modules/commander/Readme.md +1148 -0
  6. package/cli/node_modules/commander/esm.mjs +16 -0
  7. package/cli/node_modules/commander/index.js +26 -0
  8. package/cli/node_modules/commander/lib/argument.js +145 -0
  9. package/cli/node_modules/commander/lib/command.js +2179 -0
  10. package/cli/node_modules/commander/lib/error.js +43 -0
  11. package/cli/node_modules/commander/lib/help.js +462 -0
  12. package/cli/node_modules/commander/lib/option.js +329 -0
  13. package/cli/node_modules/commander/lib/suggestSimilar.js +100 -0
  14. package/cli/node_modules/commander/package-support.json +16 -0
  15. package/cli/node_modules/commander/package.json +80 -0
  16. package/cli/node_modules/commander/typings/esm.d.mts +3 -0
  17. package/cli/node_modules/commander/typings/index.d.ts +884 -0
  18. package/cli/yarn.lock +8 -0
  19. package/dist/esm/__tests__/delta-processor.test.d.ts +1 -0
  20. package/dist/esm/__tests__/delta-processor.test.js +77 -0
  21. package/dist/esm/__tests__/delta-processor.test.js.map +1 -0
  22. package/dist/esm/__tests__/firestore-schema.test.d.ts +1 -0
  23. package/dist/esm/__tests__/firestore-schema.test.js +74 -0
  24. package/dist/esm/__tests__/firestore-schema.test.js.map +1 -0
  25. package/dist/esm/__tests__/manifest-reader.test.d.ts +1 -0
  26. package/dist/esm/__tests__/manifest-reader.test.js +271 -0
  27. package/dist/esm/__tests__/manifest-reader.test.js.map +1 -0
  28. package/dist/esm/__tests__/rollout-checker.test.d.ts +1 -0
  29. package/dist/esm/__tests__/rollout-checker.test.js +210 -0
  30. package/dist/esm/__tests__/rollout-checker.test.js.map +1 -0
  31. package/dist/esm/core/config.d.ts +26 -0
  32. package/dist/esm/core/config.js +6 -0
  33. package/dist/esm/core/config.js.map +1 -1
  34. package/dist/esm/firestore/firestore-client.d.ts +109 -0
  35. package/dist/esm/firestore/firestore-client.js +260 -0
  36. package/dist/esm/firestore/firestore-client.js.map +1 -0
  37. package/dist/esm/firestore/index.d.ts +11 -0
  38. package/dist/esm/firestore/index.js +11 -0
  39. package/dist/esm/firestore/index.js.map +1 -0
  40. package/dist/esm/firestore/manifest-reader.d.ts +87 -0
  41. package/dist/esm/firestore/manifest-reader.js +294 -0
  42. package/dist/esm/firestore/manifest-reader.js.map +1 -0
  43. package/dist/esm/firestore/schema.d.ts +504 -0
  44. package/dist/esm/firestore/schema.js +69 -0
  45. package/dist/esm/firestore/schema.js.map +1 -0
  46. package/dist/esm/live-update/delta-processor.d.ts +94 -0
  47. package/dist/esm/live-update/delta-processor.js +212 -0
  48. package/dist/esm/live-update/delta-processor.js.map +1 -0
  49. package/dist/esm/live-update/rollout-checker.d.ts +86 -0
  50. package/dist/esm/live-update/rollout-checker.js +305 -0
  51. package/dist/esm/live-update/rollout-checker.js.map +1 -0
  52. package/dist/esm/live-update/version-manager.d.ts +12 -0
  53. package/dist/esm/live-update/version-manager.js +67 -0
  54. package/dist/esm/live-update/version-manager.js.map +1 -1
  55. package/dist/plugin.cjs.js +1 -1
  56. package/dist/plugin.cjs.js.map +1 -1
  57. package/dist/plugin.esm.js +1 -1
  58. package/dist/plugin.esm.js.map +1 -1
  59. package/dist/plugin.js +1 -1
  60. package/dist/plugin.js.map +1 -1
  61. package/docs/QUICK_START.md +3 -3
  62. package/docs/README.md +4 -4
  63. package/docs/api/API.md +4 -3
  64. package/docs/getting-started/installation.md +2 -2
  65. package/docs/play-console-rejection-rules.json +428 -0
  66. package/package.json +20 -18
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Delta Processor
3
+ *
4
+ * Handles delta/patch-based updates for reduced download sizes.
5
+ * Uses a simple file-level patching strategy that works in JavaScript.
6
+ *
7
+ * For production, a WASM-based bsdiff/bspatch implementation can be added
8
+ * for better performance on binary files.
9
+ */
10
+ import { Logger } from '../core/logger';
11
+ import { ConfigManager } from '../core/config';
12
+ import { DownloadError, ErrorCode, ValidationError } from '../core/errors';
13
+ /**
14
+ * Delta processor for applying patch updates
15
+ */
16
+ export class DeltaProcessor {
17
+ constructor() {
18
+ this.logger = Logger.getInstance();
19
+ this.configManager = ConfigManager.getInstance();
20
+ }
21
+ /**
22
+ * Download update with delta support
23
+ * Falls back to full download if delta fails
24
+ */
25
+ async downloadWithDelta(updateInfo, currentBundleData, onProgress) {
26
+ var _a;
27
+ const startTime = Date.now();
28
+ // Check if delta is available and we have current bundle
29
+ if (this.configManager.get('enableDeltaUpdates') &&
30
+ ((_a = updateInfo.delta) === null || _a === void 0 ? void 0 : _a.available) &&
31
+ updateInfo.delta.patchUrl &&
32
+ currentBundleData) {
33
+ try {
34
+ this.logger.info('Attempting delta update', {
35
+ patchSize: updateInfo.delta.patchSize,
36
+ fullSize: updateInfo.size,
37
+ });
38
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(10);
39
+ // Download delta patch
40
+ const patchData = await this.downloadPatch(updateInfo.delta.patchUrl);
41
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(50);
42
+ // Apply delta patch
43
+ const patchedBundle = await this.applyPatch(currentBundleData, patchData, updateInfo.delta.targetChecksum || updateInfo.checksum);
44
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(90);
45
+ // Verify result
46
+ const resultChecksum = await this.calculateChecksum(patchedBundle);
47
+ if (resultChecksum !== (updateInfo.delta.targetChecksum || updateInfo.checksum)) {
48
+ throw new ValidationError(ErrorCode.CHECKSUM_MISMATCH, 'Delta patch result checksum mismatch');
49
+ }
50
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(100);
51
+ const duration = Date.now() - startTime;
52
+ this.logger.info('Delta update successful', {
53
+ downloadSize: patchData.byteLength,
54
+ resultSize: patchedBundle.byteLength,
55
+ savings: `${Math.round((1 - patchData.byteLength / (updateInfo.size || patchedBundle.byteLength)) * 100)}%`,
56
+ duration,
57
+ });
58
+ return {
59
+ usedDelta: true,
60
+ bundleData: patchedBundle,
61
+ checksum: resultChecksum,
62
+ downloadSize: patchData.byteLength,
63
+ duration,
64
+ };
65
+ }
66
+ catch (error) {
67
+ this.logger.warn('Delta update failed, falling back to full download', { error });
68
+ // Fall through to full download
69
+ }
70
+ }
71
+ // Full download
72
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(10);
73
+ if (!updateInfo.bundleUrl) {
74
+ throw new DownloadError(ErrorCode.DOWNLOAD_FAILED, 'No bundle URL provided');
75
+ }
76
+ const fullBundle = await this.downloadFull(updateInfo.bundleUrl, onProgress);
77
+ const duration = Date.now() - startTime;
78
+ const checksum = await this.calculateChecksum(fullBundle);
79
+ // Verify checksum
80
+ if (updateInfo.checksum && checksum !== updateInfo.checksum) {
81
+ throw new ValidationError(ErrorCode.CHECKSUM_MISMATCH, 'Full bundle checksum mismatch');
82
+ }
83
+ return {
84
+ usedDelta: false,
85
+ bundleData: fullBundle,
86
+ checksum,
87
+ downloadSize: fullBundle.byteLength,
88
+ duration,
89
+ };
90
+ }
91
+ /**
92
+ * Download a delta patch file
93
+ */
94
+ async downloadPatch(url) {
95
+ const response = await fetch(url);
96
+ if (!response.ok) {
97
+ throw new DownloadError(ErrorCode.DOWNLOAD_FAILED, `Failed to download delta patch: ${response.status}`);
98
+ }
99
+ return response.arrayBuffer();
100
+ }
101
+ /**
102
+ * Download full bundle
103
+ */
104
+ async downloadFull(url, onProgress) {
105
+ const response = await fetch(url);
106
+ if (!response.ok) {
107
+ throw new DownloadError(ErrorCode.DOWNLOAD_FAILED, `Failed to download bundle: ${response.status}`);
108
+ }
109
+ // If we can track progress
110
+ const contentLength = response.headers.get('content-length');
111
+ const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
112
+ if (totalBytes && response.body) {
113
+ const reader = response.body.getReader();
114
+ const chunks = [];
115
+ let receivedBytes = 0;
116
+ while (true) {
117
+ const { done, value } = await reader.read();
118
+ if (done)
119
+ break;
120
+ chunks.push(value);
121
+ receivedBytes += value.length;
122
+ if (onProgress) {
123
+ const percent = Math.round((receivedBytes / totalBytes) * 90) + 10;
124
+ onProgress(Math.min(percent, 99));
125
+ }
126
+ }
127
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(100);
128
+ // Combine chunks
129
+ const result = new Uint8Array(receivedBytes);
130
+ let offset = 0;
131
+ for (const chunk of chunks) {
132
+ result.set(chunk, offset);
133
+ offset += chunk.length;
134
+ }
135
+ return result.buffer;
136
+ }
137
+ // Simple download without progress
138
+ const data = await response.arrayBuffer();
139
+ onProgress === null || onProgress === void 0 ? void 0 : onProgress(100);
140
+ return data;
141
+ }
142
+ /**
143
+ * Apply a delta patch to create new bundle
144
+ *
145
+ * This is a simplified patch format using JSON metadata + file-level changes.
146
+ * For production binary patching, a WASM bspatch implementation would be used.
147
+ */
148
+ async applyPatch(currentBundle, patchData, _expectedChecksum) {
149
+ try {
150
+ // Try to parse as JSON patch (file-level patching)
151
+ const patchText = new TextDecoder().decode(patchData);
152
+ const patch = JSON.parse(patchText);
153
+ if (patch.type === 'file-level') {
154
+ return this.applyFileLevelPatch(currentBundle, patch);
155
+ }
156
+ // Binary patch format
157
+ return this.applyBinaryPatch(currentBundle, patchData);
158
+ }
159
+ catch (_a) {
160
+ // Treat as binary patch
161
+ return this.applyBinaryPatch(currentBundle, patchData);
162
+ }
163
+ }
164
+ /**
165
+ * Apply file-level patch (JSON format)
166
+ */
167
+ async applyFileLevelPatch(_currentBundle, _patch) {
168
+ // This would require JSZip on the client side
169
+ // For now, throw an error to fall back to full download
170
+ this.logger.debug('File-level patch not supported in plugin, falling back');
171
+ throw new Error('File-level patch not supported in plugin');
172
+ }
173
+ /**
174
+ * Apply binary patch (bsdiff format)
175
+ *
176
+ * NOTE: This is a placeholder. For production, use WASM-compiled bspatch.
177
+ */
178
+ async applyBinaryPatch(_currentBundle, _patchData) {
179
+ // Binary patching requires WASM implementation
180
+ // For now, throw an error to fall back to full download
181
+ this.logger.debug('Binary patch requires WASM module, falling back');
182
+ throw new Error('Binary patch not supported without WASM module');
183
+ }
184
+ /**
185
+ * Calculate SHA-256 checksum
186
+ */
187
+ async calculateChecksum(data) {
188
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
189
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
190
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
191
+ }
192
+ /**
193
+ * Verify checksum matches
194
+ */
195
+ async verifyChecksum(data, expectedChecksum) {
196
+ const actualChecksum = await this.calculateChecksum(data);
197
+ return actualChecksum.toLowerCase() === expectedChecksum.toLowerCase();
198
+ }
199
+ /**
200
+ * Check if delta updates are enabled
201
+ */
202
+ isDeltaEnabled() {
203
+ return this.configManager.get('enableDeltaUpdates');
204
+ }
205
+ }
206
+ /**
207
+ * Create delta processor instance
208
+ */
209
+ export function createDeltaProcessor() {
210
+ return new DeltaProcessor();
211
+ }
212
+ //# sourceMappingURL=delta-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta-processor.js","sourceRoot":"","sources":["../../../src/live-update/delta-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA0C3E;;GAEG;AACH,MAAM,OAAO,cAAc;IAIzB;QACE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IACnD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CACrB,UAA+B,EAC/B,iBAAqC,EACrC,UAAsC;;QAEtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,yDAAyD;QACzD,IACE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,oBAAoB,CAAC;aAC5C,MAAA,UAAU,CAAC,KAAK,0CAAE,SAAS,CAAA;YAC3B,UAAU,CAAC,KAAK,CAAC,QAAQ;YACzB,iBAAiB,EACjB,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;oBAC1C,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,SAAS;oBACrC,QAAQ,EAAE,UAAU,CAAC,IAAI;iBAC1B,CAAC,CAAC;gBAEH,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,EAAE,CAAC,CAAC;gBAEjB,uBAAuB;gBACvB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAEtE,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,EAAE,CAAC,CAAC;gBAEjB,oBAAoB;gBACpB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,UAAU,CACzC,iBAAiB,EACjB,SAAS,EACT,UAAU,CAAC,KAAK,CAAC,cAAc,IAAI,UAAU,CAAC,QAAS,CACxD,CAAC;gBAEF,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,EAAE,CAAC,CAAC;gBAEjB,gBAAgB;gBAChB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;gBAEnE,IAAI,cAAc,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,cAAc,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAChF,MAAM,IAAI,eAAe,CACvB,SAAS,CAAC,iBAAiB,EAC3B,sCAAsC,CACvC,CAAC;gBACJ,CAAC;gBAED,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,GAAG,CAAC,CAAC;gBAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;gBAExC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;oBAC1C,YAAY,EAAE,SAAS,CAAC,UAAU;oBAClC,UAAU,EAAE,aAAa,CAAC,UAAU;oBACpC,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,UAAU,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG;oBAC3G,QAAQ;iBACT,CAAC,CAAC;gBAEH,OAAO;oBACL,SAAS,EAAE,IAAI;oBACf,UAAU,EAAE,aAAa;oBACzB,QAAQ,EAAE,cAAc;oBACxB,YAAY,EAAE,SAAS,CAAC,UAAU;oBAClC,QAAQ;iBACT,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oDAAoD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;gBAClF,gCAAgC;YAClC,CAAC;QACH,CAAC;QAED,gBAAgB;QAChB,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,EAAE,CAAC,CAAC;QAEjB,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,aAAa,CAAC,SAAS,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QAE7E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAE1D,kBAAkB;QAClB,IAAI,UAAU,CAAC,QAAQ,IAAI,QAAQ,KAAK,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC5D,MAAM,IAAI,eAAe,CACvB,SAAS,CAAC,iBAAiB,EAC3B,+BAA+B,CAChC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,UAAU,EAAE,UAAU;YACtB,QAAQ;YACR,YAAY,EAAE,UAAU,CAAC,UAAU;YACnC,QAAQ;SACT,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,GAAW;QACrC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,aAAa,CACrB,SAAS,CAAC,eAAe,EACzB,mCAAmC,QAAQ,CAAC,MAAM,EAAE,CACrD,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,WAAW,EAAE,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CACxB,GAAW,EACX,UAAsC;QAEtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,aAAa,CACrB,SAAS,CAAC,eAAe,EACzB,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CAChD,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnE,IAAI,UAAU,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACzC,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,aAAa,GAAG,CAAC,CAAC;YAEtB,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAE5C,IAAI,IAAI;oBAAE,MAAM;gBAEhB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACnB,aAAa,IAAI,KAAK,CAAC,MAAM,CAAC;gBAE9B,IAAI,UAAU,EAAE,CAAC;oBACf,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;oBACnE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;gBACpC,CAAC;YACH,CAAC;YAED,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,GAAG,CAAC,CAAC;YAElB,iBAAiB;YACjB,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC;YAC7C,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACzB,CAAC;YAED,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAED,mCAAmC;QACnC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;QAC1C,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,GAAG,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,UAAU,CACtB,aAA0B,EAC1B,SAAsB,EACtB,iBAAyB;QAEzB,IAAI,CAAC;YACH,mDAAmD;YACnD,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAmB,CAAC;YAEtD,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAChC,OAAO,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YACxD,CAAC;YAED,sBAAsB;YACtB,OAAO,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;QAAC,WAAM,CAAC;YACP,wBAAwB;YACxB,OAAO,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAC/B,cAA2B,EAC3B,MAAsB;QAEtB,8CAA8C;QAC9C,wDAAwD;QACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,gBAAgB,CAC5B,cAA2B,EAC3B,UAAuB;QAEvB,+CAA+C;QAC/C,wDAAwD;QACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,IAAiB;QACvC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;QACzD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,IAAiB,EAAE,gBAAwB;QAC9D,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC1D,OAAO,cAAc,CAAC,WAAW,EAAE,KAAK,gBAAgB,CAAC,WAAW,EAAE,CAAC;IACzE,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IACtD,CAAC;CACF;AAiBD;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,cAAc,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Rollout Checker
3
+ *
4
+ * Client-side rollout eligibility checking for staged deployments.
5
+ * Uses deterministic hashing for consistent rollout decisions.
6
+ */
7
+ import type { RolloutConfig, DeviceInfo } from '../firestore/schema';
8
+ /**
9
+ * Rollout eligibility result
10
+ */
11
+ export interface RolloutEligibilityResult {
12
+ /** Whether device is eligible for the update */
13
+ eligible: boolean;
14
+ /** Reason for the eligibility decision */
15
+ reason: string;
16
+ /** Device's calculated percentile (0-100) */
17
+ devicePercentile?: number;
18
+ /** Current rollout percentage */
19
+ currentPercentage?: number;
20
+ }
21
+ /**
22
+ * Rollout checker for determining update eligibility
23
+ */
24
+ export declare class RolloutChecker {
25
+ private readonly logger;
26
+ private readonly configManager;
27
+ private deviceInfoCache;
28
+ constructor();
29
+ /**
30
+ * Check if device is eligible for update based on rollout config
31
+ */
32
+ checkEligibility(rollout: RolloutConfig, deviceInfo: DeviceInfo): Promise<RolloutEligibilityResult>;
33
+ /**
34
+ * Check time window for rollout
35
+ */
36
+ private checkTimeWindow;
37
+ /**
38
+ * Check scheduled start time
39
+ */
40
+ private checkScheduled;
41
+ /**
42
+ * Check target segments
43
+ */
44
+ private checkSegments;
45
+ /**
46
+ * Calculate current rollout percentage based on schedule
47
+ */
48
+ private calculateCurrentPercentage;
49
+ /**
50
+ * Get deterministic percentile for device ID
51
+ * Uses SHA-256 hash for uniform distribution
52
+ */
53
+ getDevicePercentile(deviceId: string): Promise<number>;
54
+ /**
55
+ * Hash a string using SHA-256
56
+ */
57
+ private hashString;
58
+ /**
59
+ * Convert hash to percentile (0-100)
60
+ */
61
+ private hashToPercentile;
62
+ /**
63
+ * Compare semantic versions
64
+ */
65
+ private compareVersions;
66
+ /**
67
+ * Set cached device info
68
+ */
69
+ setDeviceInfo(deviceInfo: DeviceInfo): void;
70
+ /**
71
+ * Get cached device info
72
+ */
73
+ getDeviceInfo(): DeviceInfo | null;
74
+ /**
75
+ * Check if staged rollouts are enabled
76
+ */
77
+ isEnabled(): boolean;
78
+ }
79
+ /**
80
+ * Create rollout checker instance
81
+ */
82
+ export declare function createRolloutChecker(): RolloutChecker;
83
+ /**
84
+ * Collect device information for rollout eligibility
85
+ */
86
+ export declare function collectDeviceInfo(): Promise<DeviceInfo>;
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Rollout Checker
3
+ *
4
+ * Client-side rollout eligibility checking for staged deployments.
5
+ * Uses deterministic hashing for consistent rollout decisions.
6
+ */
7
+ import { timestampToDate } from '../firestore/schema';
8
+ import { Logger } from '../core/logger';
9
+ import { ConfigManager } from '../core/config';
10
+ /**
11
+ * Rollout checker for determining update eligibility
12
+ */
13
+ export class RolloutChecker {
14
+ constructor() {
15
+ this.deviceInfoCache = null;
16
+ this.logger = Logger.getInstance();
17
+ this.configManager = ConfigManager.getInstance();
18
+ }
19
+ /**
20
+ * Check if device is eligible for update based on rollout config
21
+ */
22
+ async checkEligibility(rollout, deviceInfo) {
23
+ var _a;
24
+ // If rollouts are disabled in config, always eligible
25
+ if (!this.configManager.get('enableStagedRollouts')) {
26
+ return { eligible: true, reason: 'Staged rollouts disabled in config' };
27
+ }
28
+ // If rollout is not enabled, all devices are eligible
29
+ if (!rollout.enabled) {
30
+ return { eligible: true, reason: 'Rollout not enabled, all devices eligible' };
31
+ }
32
+ // Check time window
33
+ const timeCheck = this.checkTimeWindow(rollout);
34
+ if (!timeCheck.eligible) {
35
+ return timeCheck;
36
+ }
37
+ // Check scheduled rollout
38
+ if (((_a = rollout.schedule) === null || _a === void 0 ? void 0 : _a.type) === 'scheduled' && rollout.schedule.scheduledTime) {
39
+ const scheduledCheck = this.checkScheduled(rollout.schedule.scheduledTime);
40
+ if (!scheduledCheck.eligible) {
41
+ return scheduledCheck;
42
+ }
43
+ }
44
+ // Check target segments
45
+ if (rollout.targetSegments) {
46
+ const segmentCheck = this.checkSegments(rollout.targetSegments, deviceInfo);
47
+ if (!segmentCheck.eligible) {
48
+ return segmentCheck;
49
+ }
50
+ }
51
+ // Calculate current rollout percentage
52
+ const currentPercentage = this.calculateCurrentPercentage(rollout);
53
+ // Get device percentile
54
+ const devicePercentile = await this.getDevicePercentile(deviceInfo.deviceId);
55
+ // Check if device is in rollout percentage
56
+ if (devicePercentile > currentPercentage) {
57
+ return {
58
+ eligible: false,
59
+ reason: `Device percentile ${devicePercentile.toFixed(1)}% exceeds rollout ${currentPercentage}%`,
60
+ devicePercentile,
61
+ currentPercentage,
62
+ };
63
+ }
64
+ this.logger.debug('Device eligible for update', {
65
+ devicePercentile,
66
+ currentPercentage,
67
+ });
68
+ return {
69
+ eligible: true,
70
+ reason: 'Device eligible for update',
71
+ devicePercentile,
72
+ currentPercentage,
73
+ };
74
+ }
75
+ /**
76
+ * Check time window for rollout
77
+ */
78
+ checkTimeWindow(rollout) {
79
+ const now = Date.now();
80
+ const startTime = timestampToDate(rollout.startTime).getTime();
81
+ if (now < startTime) {
82
+ return {
83
+ eligible: false,
84
+ reason: `Rollout not started yet. Starts at ${new Date(startTime).toISOString()}`,
85
+ };
86
+ }
87
+ if (rollout.endTime) {
88
+ const endTime = timestampToDate(rollout.endTime).getTime();
89
+ if (now > endTime) {
90
+ return {
91
+ eligible: false,
92
+ reason: `Rollout ended at ${new Date(endTime).toISOString()}`,
93
+ };
94
+ }
95
+ }
96
+ return { eligible: true, reason: 'Within time window' };
97
+ }
98
+ /**
99
+ * Check scheduled start time
100
+ */
101
+ checkScheduled(scheduledTime) {
102
+ const now = Date.now();
103
+ const scheduled = timestampToDate(scheduledTime).getTime();
104
+ if (now < scheduled) {
105
+ return {
106
+ eligible: false,
107
+ reason: `Scheduled for ${new Date(scheduled).toISOString()}`,
108
+ };
109
+ }
110
+ return { eligible: true, reason: 'Scheduled time passed' };
111
+ }
112
+ /**
113
+ * Check target segments
114
+ */
115
+ checkSegments(segments, deviceInfo) {
116
+ // Platform check
117
+ if (segments.platforms && segments.platforms.length > 0) {
118
+ if (!segments.platforms.includes(deviceInfo.platform)) {
119
+ return {
120
+ eligible: false,
121
+ reason: `Platform ${deviceInfo.platform} not in target list: ${segments.platforms.join(', ')}`,
122
+ };
123
+ }
124
+ }
125
+ // App version checks
126
+ if (segments.minAppVersion) {
127
+ if (this.compareVersions(deviceInfo.appVersion, segments.minAppVersion) < 0) {
128
+ return {
129
+ eligible: false,
130
+ reason: `App version ${deviceInfo.appVersion} below minimum ${segments.minAppVersion}`,
131
+ };
132
+ }
133
+ }
134
+ if (segments.maxAppVersion) {
135
+ if (this.compareVersions(deviceInfo.appVersion, segments.maxAppVersion) > 0) {
136
+ return {
137
+ eligible: false,
138
+ reason: `App version ${deviceInfo.appVersion} above maximum ${segments.maxAppVersion}`,
139
+ };
140
+ }
141
+ }
142
+ // Device ID whitelist
143
+ if (segments.deviceIds && segments.deviceIds.length > 0) {
144
+ if (!segments.deviceIds.includes(deviceInfo.deviceId)) {
145
+ return {
146
+ eligible: false,
147
+ reason: 'Device not in whitelist',
148
+ };
149
+ }
150
+ }
151
+ // Region check
152
+ if (segments.regions && segments.regions.length > 0) {
153
+ if (!deviceInfo.region || !segments.regions.includes(deviceInfo.region)) {
154
+ return {
155
+ eligible: false,
156
+ reason: `Region ${deviceInfo.region || 'unknown'} not in target list: ${segments.regions.join(', ')}`,
157
+ };
158
+ }
159
+ }
160
+ return { eligible: true, reason: 'Segment checks passed' };
161
+ }
162
+ /**
163
+ * Calculate current rollout percentage based on schedule
164
+ */
165
+ calculateCurrentPercentage(rollout) {
166
+ if (!rollout.schedule || rollout.schedule.type !== 'gradual') {
167
+ return rollout.percentage;
168
+ }
169
+ const { gradualSteps, gradualInterval } = rollout.schedule;
170
+ if (!gradualSteps || !gradualInterval) {
171
+ return rollout.percentage;
172
+ }
173
+ const startTime = timestampToDate(rollout.startTime).getTime();
174
+ const elapsedHours = (Date.now() - startTime) / (1000 * 60 * 60);
175
+ const stepIndex = Math.floor(elapsedHours / gradualInterval);
176
+ if (stepIndex >= gradualSteps.length) {
177
+ return gradualSteps[gradualSteps.length - 1];
178
+ }
179
+ return gradualSteps[stepIndex];
180
+ }
181
+ /**
182
+ * Get deterministic percentile for device ID
183
+ * Uses SHA-256 hash for uniform distribution
184
+ */
185
+ async getDevicePercentile(deviceId) {
186
+ const hash = await this.hashString(deviceId);
187
+ return this.hashToPercentile(hash);
188
+ }
189
+ /**
190
+ * Hash a string using SHA-256
191
+ */
192
+ async hashString(input) {
193
+ const encoder = new TextEncoder();
194
+ const data = encoder.encode(input);
195
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
196
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
197
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
198
+ }
199
+ /**
200
+ * Convert hash to percentile (0-100)
201
+ */
202
+ hashToPercentile(hash) {
203
+ const hashInt = parseInt(hash.substring(0, 8), 16);
204
+ const maxInt = parseInt('ffffffff', 16);
205
+ return (hashInt / maxInt) * 100;
206
+ }
207
+ /**
208
+ * Compare semantic versions
209
+ */
210
+ compareVersions(v1, v2) {
211
+ const cleanV1 = v1.split('-')[0];
212
+ const cleanV2 = v2.split('-')[0];
213
+ const parts1 = cleanV1.split('.').map(Number);
214
+ const parts2 = cleanV2.split('.').map(Number);
215
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
216
+ const p1 = parts1[i] || 0;
217
+ const p2 = parts2[i] || 0;
218
+ if (p1 > p2)
219
+ return 1;
220
+ if (p1 < p2)
221
+ return -1;
222
+ }
223
+ return 0;
224
+ }
225
+ /**
226
+ * Set cached device info
227
+ */
228
+ setDeviceInfo(deviceInfo) {
229
+ this.deviceInfoCache = deviceInfo;
230
+ }
231
+ /**
232
+ * Get cached device info
233
+ */
234
+ getDeviceInfo() {
235
+ return this.deviceInfoCache;
236
+ }
237
+ /**
238
+ * Check if staged rollouts are enabled
239
+ */
240
+ isEnabled() {
241
+ return this.configManager.get('enableStagedRollouts');
242
+ }
243
+ }
244
+ /**
245
+ * Create rollout checker instance
246
+ */
247
+ export function createRolloutChecker() {
248
+ return new RolloutChecker();
249
+ }
250
+ /**
251
+ * Collect device information for rollout eligibility
252
+ */
253
+ export async function collectDeviceInfo() {
254
+ // Try to get Capacitor device info if available
255
+ let platform = 'web';
256
+ let osVersion = '';
257
+ try {
258
+ const { Device } = await import('@capacitor/device');
259
+ const info = await Device.getInfo();
260
+ platform = info.platform;
261
+ osVersion = info.osVersion;
262
+ }
263
+ catch (_a) {
264
+ // Running in web or Device plugin not available
265
+ platform = 'web';
266
+ osVersion = navigator.userAgent;
267
+ }
268
+ // Get or generate device ID
269
+ let deviceId = '';
270
+ try {
271
+ const { Preferences } = await import('@capacitor/preferences');
272
+ const { value } = await Preferences.get({ key: 'native_update_device_id' });
273
+ if (value) {
274
+ deviceId = value;
275
+ }
276
+ else {
277
+ deviceId = crypto.randomUUID();
278
+ await Preferences.set({ key: 'native_update_device_id', value: deviceId });
279
+ }
280
+ }
281
+ catch (_b) {
282
+ // Generate a session-based ID
283
+ deviceId = `web_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
284
+ }
285
+ // Get app version
286
+ let appVersion = '1.0.0';
287
+ try {
288
+ const { App } = await import('@capacitor/app');
289
+ const info = await App.getInfo();
290
+ appVersion = info.version;
291
+ }
292
+ catch (_c) {
293
+ // Use default version
294
+ }
295
+ return {
296
+ deviceId,
297
+ platform,
298
+ appVersion,
299
+ bundleVersion: '1.0.0', // Will be updated by the plugin
300
+ osVersion,
301
+ locale: navigator.language,
302
+ region: undefined, // Could be determined via geolocation or timezone
303
+ };
304
+ }
305
+ //# sourceMappingURL=rollout-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollout-checker.js","sourceRoot":"","sources":["../../../src/live-update/rollout-checker.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { LatestVersion } from '../definitions';
2
+ import type { DeviceInfo, UpdateCheckResponse } from '../firestore/schema';
2
3
  /**
3
4
  * Manages version checking and comparison
4
5
  */
@@ -10,6 +11,8 @@ export declare class VersionManager {
10
11
  private readonly securityValidator;
11
12
  private preferences;
12
13
  private memoryCache;
14
+ private firestoreClient;
15
+ private manifestReader;
13
16
  constructor();
14
17
  /**
15
18
  * Compare two semantic versions
@@ -27,6 +30,15 @@ export declare class VersionManager {
27
30
  * Initialize the version manager
28
31
  */
29
32
  initialize(): Promise<void>;
33
+ /**
34
+ * Check for updates from Firestore backend
35
+ * Uses ManifestReader for efficient single-document reads
36
+ */
37
+ checkForUpdatesFromFirestore(currentVersion: string, deviceInfo: DeviceInfo): Promise<UpdateCheckResponse | null>;
38
+ /**
39
+ * Get the appropriate update checker based on backend type
40
+ */
41
+ checkForUpdatesAuto(currentVersion: string, deviceInfo?: DeviceInfo): Promise<LatestVersion | UpdateCheckResponse | null>;
30
42
  /**
31
43
  * Check for latest version from server
32
44
  */