native-update 2.0.0 → 3.1.0

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 (258) hide show
  1. package/Readme.md +28 -14
  2. package/android/manifest-additions.xml +28 -0
  3. package/android/src/main/AndroidManifest.xml +3 -7
  4. package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundNotificationManager.kt +21 -13
  5. package/android/src/main/java/com/aoneahsan/nativeupdate/LiveUpdatePlugin.kt +196 -29
  6. package/android/src/main/java/com/aoneahsan/nativeupdate/NativeUpdatePlugin.kt +21 -36
  7. package/cli/AGENTS.md +15 -1
  8. package/cli/CLAUDE.md +15 -1
  9. package/cli/commands/backend-create.js +56 -15
  10. package/cli/commands/bundle-create.js +39 -7
  11. package/cli/commands/monitor.js +72 -51
  12. package/cli/index.js +10 -24
  13. package/cli/package.json +11 -3
  14. package/dist/esm/app-review/app-review-manager.js +0 -1
  15. package/dist/esm/app-review/index.js +0 -1
  16. package/dist/esm/app-review/platform-review-handler.js +0 -1
  17. package/dist/esm/app-review/review-conditions-checker.js +0 -1
  18. package/dist/esm/app-review/review-rate-limiter.js +0 -1
  19. package/dist/esm/app-review/types.js +0 -1
  20. package/dist/esm/app-update/app-update-checker.js +0 -1
  21. package/dist/esm/app-update/app-update-installer.d.ts +1 -0
  22. package/dist/esm/app-update/app-update-installer.js +19 -8
  23. package/dist/esm/app-update/app-update-manager.js +0 -1
  24. package/dist/esm/app-update/app-update-notifier.js +0 -1
  25. package/dist/esm/app-update/index.js +0 -1
  26. package/dist/esm/app-update/platform-app-update.js +12 -3
  27. package/dist/esm/app-update/types.js +0 -1
  28. package/dist/esm/background-update/background-scheduler.js +0 -1
  29. package/dist/esm/background-update/index.js +0 -1
  30. package/dist/esm/background-update/notification-manager.js +0 -1
  31. package/dist/esm/config/support.js +0 -1
  32. package/dist/esm/core/analytics.d.ts +13 -0
  33. package/dist/esm/core/analytics.js +15 -1
  34. package/dist/esm/core/cache-manager.js +0 -1
  35. package/dist/esm/core/config.d.ts +0 -15
  36. package/dist/esm/core/config.js +0 -4
  37. package/dist/esm/core/errors.d.ts +1 -0
  38. package/dist/esm/core/errors.js +1 -1
  39. package/dist/esm/core/event-emitter.d.ts +0 -3
  40. package/dist/esm/core/event-emitter.js +8 -3
  41. package/dist/esm/core/logger.js +0 -1
  42. package/dist/esm/core/performance.js +0 -1
  43. package/dist/esm/core/plugin-manager.js +3 -1
  44. package/dist/esm/core/security.d.ts +11 -0
  45. package/dist/esm/core/security.js +27 -1
  46. package/dist/esm/definitions.d.ts +0 -11
  47. package/dist/esm/definitions.js +0 -1
  48. package/dist/esm/index.d.ts +3 -2
  49. package/dist/esm/index.js +3 -1
  50. package/dist/esm/live-update/bundle-manager.d.ts +8 -0
  51. package/dist/esm/live-update/bundle-manager.js +20 -1
  52. package/dist/esm/live-update/certificate-pinning.js +0 -1
  53. package/dist/esm/live-update/delta-processor.d.ts +1 -1
  54. package/dist/esm/live-update/delta-processor.js +3 -1
  55. package/dist/esm/live-update/download-manager.js +9 -2
  56. package/dist/esm/live-update/rollout-checker.d.ts +1 -1
  57. package/dist/esm/live-update/rollout-checker.js +5 -6
  58. package/dist/esm/live-update/update-manager.js +0 -1
  59. package/dist/esm/live-update/version-manager.d.ts +0 -12
  60. package/dist/esm/live-update/version-manager.js +0 -68
  61. package/dist/esm/plugin.js +69 -43
  62. package/dist/esm/security/crypto.js +11 -7
  63. package/dist/esm/security/validator.js +0 -1
  64. package/dist/esm/types/rollout.d.ts +85 -0
  65. package/dist/esm/types/rollout.js +25 -0
  66. package/dist/esm/web.d.ts +8 -0
  67. package/dist/esm/web.js +148 -54
  68. package/dist/plugin.cjs.js +1 -2
  69. package/dist/plugin.esm.js +1 -2
  70. package/dist/plugin.js +2 -3
  71. package/docs/CHANGELOG.md +124 -0
  72. package/docs/CLAUDE.md +1 -1
  73. package/docs/MANUAL-TASKS.md +17 -0
  74. package/docs/MARKETING_WEBSITE_TRACKER.md +18 -2
  75. package/docs/MIGRATION.md +83 -0
  76. package/docs/PACKAGES.md +167 -0
  77. package/docs/PERFORMANCE.md +110 -0
  78. package/docs/PROJECT_COMPLETION_TRACKER.md +4 -35
  79. package/docs/README.md +0 -1
  80. package/docs/REMAINING_FEATURES.md +123 -76
  81. package/docs/ROADMAP.md +200 -120
  82. package/docs/SECURITY-IF-REPO-PUBLIC.md +232 -0
  83. package/docs/TESTING_REQUIREMENTS.md +1 -112
  84. package/docs/ai-knowledge-base/00-project-profile.md +38 -0
  85. package/docs/ai-knowledge-base/01-features.md +46 -0
  86. package/docs/ai-knowledge-base/02-routes.md +72 -0
  87. package/docs/ai-knowledge-base/03-tech-stack.md +57 -0
  88. package/docs/ai-knowledge-base/README.md +23 -0
  89. package/docs/analytics-tracking.md +37 -0
  90. package/docs/capacitor-official-plugins.md +46 -0
  91. package/docs/capawesome-plugins.md +29 -0
  92. package/docs/deployment/HOSTINGER_DEPLOY.md +75 -34
  93. package/docs/deployment/PRODUCTION-DEPLOY-CHECKLIST.md +184 -0
  94. package/docs/docs-site/plan.md +201 -0
  95. package/docs/docs-site/scope.md +127 -0
  96. package/docs/docs-site/tracker.json +235 -0
  97. package/docs/error-handling-tracking.md +37 -0
  98. package/docs/guides/testing-guide.md +15 -41
  99. package/docs/package-audit.md +41 -0
  100. package/docs/play-store/ASO-METADATA.md +5 -0
  101. package/docs/play-store/DATA-SAFETY.md +5 -0
  102. package/docs/play-store/DECLARATIONS.md +5 -0
  103. package/docs/play-store/README.md +27 -0
  104. package/docs/play-store/RELEASE-NOTES.md +99 -0
  105. package/docs/play-store/RELEASE-STEPS.md +6 -0
  106. package/docs/play-store/STORE-LISTING.md +7 -0
  107. package/docs/play-store/SUBMISSION-CHECKLIST.md +5 -0
  108. package/docs/production-readiness.md +1 -1
  109. package/docs/project-audit/2026-05-16/00-FINALIZATION-PLAN.md +123 -0
  110. package/docs/project-audit/2026-05-16/01-BATCH-PLAN.md +227 -0
  111. package/docs/project-audit/2026-05-16/02-AUDIT-FINDINGS.md +144 -0
  112. package/docs/project-audit/2026-05-16/sessions/batch-01.md +42 -0
  113. package/docs/project-audit/2026-05-16/sessions/batch-02.md +74 -0
  114. package/docs/project-audit/2026-05-16/sessions/batch-03.md +71 -0
  115. package/docs/project-audit/2026-05-16/sessions/batch-04.md +88 -0
  116. package/docs/project-audit/2026-05-16/sessions/batch-05.md +63 -0
  117. package/docs/project-audit/2026-05-16/sessions/batch-06.md +103 -0
  118. package/docs/project-audit/2026-05-16/sessions/batch-07.md +61 -0
  119. package/docs/project-audit/2026-05-16/sessions/batch-08.md +101 -0
  120. package/docs/project-audit/2026-05-16/sessions/batch-09.md +105 -0
  121. package/docs/project-audit/2026-05-16/sessions/batch-10.md +102 -0
  122. package/docs/project-audit/AUDIT-HISTORY.md +74 -0
  123. package/docs/project-audit/BATCH-PLAN.md +168 -0
  124. package/docs/project-audit/MARKETING-WEBSITE-FINDINGS-2026-05-11.md +73 -0
  125. package/docs/project-audit/PRODUCTION-READINESS-AUDIT-2026-05-08.md +275 -0
  126. package/docs/project-finalization/00-tracker.json +60 -0
  127. package/docs/project-knowledge-base/01-system-overview.md +39 -30
  128. package/docs/project-knowledge-base/02-routes-pages-forms-users.md +87 -81
  129. package/docs/project-knowledge-base/03-tech-stack-modules-services.md +140 -108
  130. package/docs/project-knowledge-base/04-data-models-integrations.md +191 -254
  131. package/docs/project-knowledge-base/05-docs-corpus-inventory.md +83 -20
  132. package/docs/project-knowledge-base/06-operations-testing-legal-content.md +67 -29
  133. package/docs/project-knowledge-base/README.md +27 -14
  134. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-05-19.md +81 -0
  135. package/docs/rules-tracker.md +102 -0
  136. package/docs/security/PRE-LAUNCH-PENTEST-CHECKLIST.md +116 -0
  137. package/docs/social-media-marketing/README.md +81 -0
  138. package/docs/social-media-marketing/posts-batch-01.md +613 -0
  139. package/docs/social-media-marketing/posts-batch-02.md +528 -0
  140. package/docs/social-media-marketing/whatsapp-messages-batch-01.md +458 -0
  141. package/docs/social-media-marketing/whatsapp-status-batch-01.md +355 -0
  142. package/docs/tracking/finalization-2026-05-16-tracker.json +346 -0
  143. package/docs/tracking/full-audit-tracker.json +121 -0
  144. package/docs/tracking/production-readiness-audit-tracker.json +429 -0
  145. package/ios/Plugin/BackgroundUpdate/BackgroundUpdatePlugin.swift +16 -3
  146. package/ios/Plugin/LiveUpdate/LiveUpdatePlugin.swift +71 -47
  147. package/ios/Plugin/NativeUpdatePlugin.swift +14 -9
  148. package/package.json +29 -29
  149. package/cli/node_modules/.yarn-integrity +0 -16
  150. package/cli/node_modules/commander/LICENSE +0 -22
  151. package/cli/node_modules/commander/Readme.md +0 -1148
  152. package/cli/node_modules/commander/esm.mjs +0 -16
  153. package/cli/node_modules/commander/index.js +0 -26
  154. package/cli/node_modules/commander/lib/argument.js +0 -145
  155. package/cli/node_modules/commander/lib/command.js +0 -2179
  156. package/cli/node_modules/commander/lib/error.js +0 -43
  157. package/cli/node_modules/commander/lib/help.js +0 -462
  158. package/cli/node_modules/commander/lib/option.js +0 -329
  159. package/cli/node_modules/commander/lib/suggestSimilar.js +0 -100
  160. package/cli/node_modules/commander/package-support.json +0 -16
  161. package/cli/node_modules/commander/package.json +0 -80
  162. package/cli/node_modules/commander/typings/esm.d.mts +0 -3
  163. package/cli/node_modules/commander/typings/index.d.ts +0 -884
  164. package/cli/yarn.lock +0 -8
  165. package/dist/esm/__tests__/bundle-manager.test.d.ts +0 -1
  166. package/dist/esm/__tests__/bundle-manager.test.js +0 -151
  167. package/dist/esm/__tests__/bundle-manager.test.js.map +0 -1
  168. package/dist/esm/__tests__/config.test.d.ts +0 -1
  169. package/dist/esm/__tests__/config.test.js +0 -70
  170. package/dist/esm/__tests__/config.test.js.map +0 -1
  171. package/dist/esm/__tests__/delta-processor.test.d.ts +0 -1
  172. package/dist/esm/__tests__/delta-processor.test.js +0 -77
  173. package/dist/esm/__tests__/delta-processor.test.js.map +0 -1
  174. package/dist/esm/__tests__/firestore-schema.test.d.ts +0 -1
  175. package/dist/esm/__tests__/firestore-schema.test.js +0 -74
  176. package/dist/esm/__tests__/firestore-schema.test.js.map +0 -1
  177. package/dist/esm/__tests__/integration.test.d.ts +0 -1
  178. package/dist/esm/__tests__/integration.test.js +0 -78
  179. package/dist/esm/__tests__/integration.test.js.map +0 -1
  180. package/dist/esm/__tests__/manifest-reader.test.d.ts +0 -1
  181. package/dist/esm/__tests__/manifest-reader.test.js +0 -271
  182. package/dist/esm/__tests__/manifest-reader.test.js.map +0 -1
  183. package/dist/esm/__tests__/rollout-checker.test.d.ts +0 -1
  184. package/dist/esm/__tests__/rollout-checker.test.js +0 -210
  185. package/dist/esm/__tests__/rollout-checker.test.js.map +0 -1
  186. package/dist/esm/__tests__/security-enforcement.test.d.ts +0 -1
  187. package/dist/esm/__tests__/security-enforcement.test.js +0 -95
  188. package/dist/esm/__tests__/security-enforcement.test.js.map +0 -1
  189. package/dist/esm/__tests__/security.test.d.ts +0 -1
  190. package/dist/esm/__tests__/security.test.js +0 -54
  191. package/dist/esm/__tests__/security.test.js.map +0 -1
  192. package/dist/esm/__tests__/version-manager.test.d.ts +0 -1
  193. package/dist/esm/__tests__/version-manager.test.js +0 -45
  194. package/dist/esm/__tests__/version-manager.test.js.map +0 -1
  195. package/dist/esm/app-review/app-review-manager.js.map +0 -1
  196. package/dist/esm/app-review/index.js.map +0 -1
  197. package/dist/esm/app-review/platform-review-handler.js.map +0 -1
  198. package/dist/esm/app-review/review-conditions-checker.js.map +0 -1
  199. package/dist/esm/app-review/review-rate-limiter.js.map +0 -1
  200. package/dist/esm/app-review/types.js.map +0 -1
  201. package/dist/esm/app-update/app-update-checker.js.map +0 -1
  202. package/dist/esm/app-update/app-update-installer.js.map +0 -1
  203. package/dist/esm/app-update/app-update-manager.js.map +0 -1
  204. package/dist/esm/app-update/app-update-notifier.js.map +0 -1
  205. package/dist/esm/app-update/index.js.map +0 -1
  206. package/dist/esm/app-update/platform-app-update.js.map +0 -1
  207. package/dist/esm/app-update/types.js.map +0 -1
  208. package/dist/esm/background-update/background-scheduler.js.map +0 -1
  209. package/dist/esm/background-update/index.js.map +0 -1
  210. package/dist/esm/background-update/notification-manager.js.map +0 -1
  211. package/dist/esm/config/support.js.map +0 -1
  212. package/dist/esm/core/analytics.js.map +0 -1
  213. package/dist/esm/core/cache-manager.js.map +0 -1
  214. package/dist/esm/core/config.js.map +0 -1
  215. package/dist/esm/core/errors.js.map +0 -1
  216. package/dist/esm/core/event-emitter.js.map +0 -1
  217. package/dist/esm/core/logger.js.map +0 -1
  218. package/dist/esm/core/performance.js.map +0 -1
  219. package/dist/esm/core/plugin-manager.js.map +0 -1
  220. package/dist/esm/core/security.js.map +0 -1
  221. package/dist/esm/definitions.js.map +0 -1
  222. package/dist/esm/firestore/firestore-client.d.ts +0 -109
  223. package/dist/esm/firestore/firestore-client.js +0 -264
  224. package/dist/esm/firestore/firestore-client.js.map +0 -1
  225. package/dist/esm/firestore/index.d.ts +0 -11
  226. package/dist/esm/firestore/index.js +0 -11
  227. package/dist/esm/firestore/index.js.map +0 -1
  228. package/dist/esm/firestore/manifest-reader.d.ts +0 -87
  229. package/dist/esm/firestore/manifest-reader.js +0 -294
  230. package/dist/esm/firestore/manifest-reader.js.map +0 -1
  231. package/dist/esm/firestore/schema.d.ts +0 -507
  232. package/dist/esm/firestore/schema.js +0 -73
  233. package/dist/esm/firestore/schema.js.map +0 -1
  234. package/dist/esm/index.js.map +0 -1
  235. package/dist/esm/live-update/bundle-manager.js.map +0 -1
  236. package/dist/esm/live-update/certificate-pinning.js.map +0 -1
  237. package/dist/esm/live-update/delta-processor.js.map +0 -1
  238. package/dist/esm/live-update/download-manager.js.map +0 -1
  239. package/dist/esm/live-update/rollout-checker.js.map +0 -1
  240. package/dist/esm/live-update/update-manager.js.map +0 -1
  241. package/dist/esm/live-update/version-manager.js.map +0 -1
  242. package/dist/esm/plugin.js.map +0 -1
  243. package/dist/esm/security/crypto.js.map +0 -1
  244. package/dist/esm/security/validator.js.map +0 -1
  245. package/dist/esm/web.js.map +0 -1
  246. package/dist/plugin.cjs.js.map +0 -1
  247. package/dist/plugin.esm.js.map +0 -1
  248. package/dist/plugin.js.map +0 -1
  249. package/docs/FIREBASE_INTEGRATION_TRACKER.md +0 -321
  250. package/docs/FIREBASE_QUERIES_AND_INDEXES_AUDIT.md +0 -221
  251. package/docs/examples/firebase-backend-example.md +0 -27
  252. package/docs/features/laravel-nova-backend/credentials.ignore.md +0 -34
  253. package/docs/guides/no-cost-backend-implementation-plan.md +0 -77
  254. package/docs/guides/no-cost-firestore-google-drive-backend.md +0 -60
  255. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-03-16.md +0 -454
  256. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-03-24.md +0 -66
  257. package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-03-25.md +0 -67
  258. /package/docs/{MARKETING_WEBSITE_PLAN.md → archive/MARKETING_WEBSITE_PLAN.md} +0 -0
@@ -1,264 +0,0 @@
1
- /**
2
- * Firestore Client
3
- *
4
- * Lightweight Firestore client for reading update manifests.
5
- * Uses Firebase REST API to avoid SDK bundle size in the plugin.
6
- *
7
- * For the admin dashboard, the full Firebase SDK is used instead.
8
- */
9
- import { COLLECTIONS, getManifestId } from './schema';
10
- import { Logger } from '../core/logger';
11
- /**
12
- * Firestore client for reading manifests
13
- */
14
- export class FirestoreClient {
15
- constructor(config) {
16
- var _a;
17
- this.cache = new Map();
18
- this.config = {
19
- projectId: config.projectId,
20
- databaseId: config.databaseId || '(default)',
21
- apiKey: config.apiKey || '',
22
- appId: config.appId,
23
- channel: config.channel,
24
- cacheDuration: config.cacheDuration || 5 * 60 * 1000, // 5 minutes default
25
- enableOffline: (_a = config.enableOffline) !== null && _a !== void 0 ? _a : true,
26
- };
27
- this.logger = Logger.getInstance();
28
- }
29
- /**
30
- * Get or create singleton instance
31
- */
32
- static getInstance(config) {
33
- if (!FirestoreClient.instance && config) {
34
- FirestoreClient.instance = new FirestoreClient(config);
35
- }
36
- if (!FirestoreClient.instance) {
37
- throw new Error('FirestoreClient not initialized. Call with config first.');
38
- }
39
- return FirestoreClient.instance;
40
- }
41
- /**
42
- * Reset singleton instance (for testing)
43
- */
44
- static resetInstance() {
45
- FirestoreClient.instance = null;
46
- }
47
- /**
48
- * Get the Firestore REST API base URL
49
- */
50
- getBaseUrl() {
51
- const db = this.config.databaseId;
52
- return `https://firestore.googleapis.com/v1/projects/${this.config.projectId}/databases/${db}/documents`;
53
- }
54
- /**
55
- * Read a document from Firestore
56
- */
57
- async getDocument(collection, documentId) {
58
- const cacheKey = `${collection}/${documentId}`;
59
- // Check cache first
60
- const cached = this.getFromCache(cacheKey);
61
- if (cached !== null) {
62
- this.logger.debug('Firestore cache hit', { collection, documentId });
63
- return cached;
64
- }
65
- const url = `${this.getBaseUrl()}/${collection}/${documentId}`;
66
- try {
67
- this.logger.debug('Fetching Firestore document', { url });
68
- const response = await fetch(url, {
69
- method: 'GET',
70
- headers: {
71
- 'Content-Type': 'application/json',
72
- },
73
- });
74
- if (response.status === 404) {
75
- this.logger.debug('Firestore document not found', {
76
- collection,
77
- documentId,
78
- });
79
- return null;
80
- }
81
- if (!response.ok) {
82
- throw new Error(`Firestore error: ${response.status} ${response.statusText}`);
83
- }
84
- const restDoc = (await response.json());
85
- const data = this.parseDocument(restDoc);
86
- // Cache the result
87
- this.setCache(cacheKey, data);
88
- return data;
89
- }
90
- catch (error) {
91
- this.logger.error('Firestore fetch error', error);
92
- // Try to return stale cache if available
93
- const staleCache = this.getFromCache(cacheKey, true);
94
- if (staleCache !== null) {
95
- this.logger.warn('Using stale cache due to fetch error');
96
- return staleCache;
97
- }
98
- throw error;
99
- }
100
- }
101
- /**
102
- * Get update manifest for current app and channel
103
- */
104
- async getManifest() {
105
- if (this.config.apiKey) {
106
- return this.getDocument(`apiKeys/${this.config.apiKey}/manifests`, this.config.channel);
107
- }
108
- const manifestId = getManifestId(this.config.appId, this.config.channel);
109
- return this.getDocument(COLLECTIONS.MANIFESTS, manifestId);
110
- }
111
- /**
112
- * Get manifest for a specific app and channel
113
- */
114
- async getManifestFor(appId, channel) {
115
- const manifestId = getManifestId(appId, channel);
116
- return this.getDocument(COLLECTIONS.MANIFESTS, manifestId);
117
- }
118
- /**
119
- * Parse Firestore REST document to TypeScript object
120
- */
121
- parseDocument(doc) {
122
- return this.parseValue({ mapValue: { fields: doc.fields } });
123
- }
124
- /**
125
- * Parse a Firestore value to native JavaScript type
126
- */
127
- parseValue(value) {
128
- if ('stringValue' in value) {
129
- return value.stringValue;
130
- }
131
- if ('integerValue' in value) {
132
- return parseInt(value.integerValue, 10);
133
- }
134
- if ('doubleValue' in value) {
135
- return value.doubleValue;
136
- }
137
- if ('booleanValue' in value) {
138
- return value.booleanValue;
139
- }
140
- if ('nullValue' in value) {
141
- return null;
142
- }
143
- if ('timestampValue' in value) {
144
- return this.parseTimestamp(value.timestampValue);
145
- }
146
- if ('mapValue' in value) {
147
- const result = {};
148
- const fields = value.mapValue.fields || {};
149
- for (const [key, val] of Object.entries(fields)) {
150
- result[key] = this.parseValue(val);
151
- }
152
- return result;
153
- }
154
- if ('arrayValue' in value) {
155
- const values = value.arrayValue.values || [];
156
- return values.map((v) => this.parseValue(v));
157
- }
158
- return null;
159
- }
160
- /**
161
- * Parse ISO timestamp to FirestoreTimestamp
162
- */
163
- parseTimestamp(isoString) {
164
- const date = new Date(isoString);
165
- return {
166
- seconds: Math.floor(date.getTime() / 1000),
167
- nanoseconds: (date.getTime() % 1000) * 1000000,
168
- };
169
- }
170
- /**
171
- * Get value from cache
172
- */
173
- getFromCache(key, allowStale = false) {
174
- const entry = this.cache.get(key);
175
- if (!entry) {
176
- return null;
177
- }
178
- const now = Date.now();
179
- if (now < entry.expiresAt || allowStale) {
180
- return entry.data;
181
- }
182
- // Cache expired
183
- return null;
184
- }
185
- /**
186
- * Set value in cache
187
- */
188
- setCache(key, data) {
189
- const now = Date.now();
190
- this.cache.set(key, {
191
- data,
192
- timestamp: now,
193
- expiresAt: now + this.config.cacheDuration,
194
- });
195
- }
196
- /**
197
- * Clear all cached data
198
- */
199
- clearCache() {
200
- this.cache.clear();
201
- this.logger.debug('Firestore cache cleared');
202
- }
203
- /**
204
- * Clear specific cache entry
205
- */
206
- clearCacheEntry(collection, documentId) {
207
- const key = `${collection}/${documentId}`;
208
- this.cache.delete(key);
209
- }
210
- /**
211
- * Get cache statistics
212
- */
213
- getCacheStats() {
214
- return {
215
- size: this.cache.size,
216
- keys: Array.from(this.cache.keys()),
217
- };
218
- }
219
- /**
220
- * Get current configuration
221
- */
222
- getConfig() {
223
- return Object.assign({}, this.config);
224
- }
225
- /**
226
- * Update channel
227
- */
228
- setChannel(channel) {
229
- this.config.channel = channel;
230
- this.clearCache(); // Clear cache when channel changes
231
- }
232
- /**
233
- * Check if client is properly configured
234
- */
235
- isConfigured() {
236
- return !!(this.config.projectId &&
237
- this.config.appId &&
238
- this.config.channel);
239
- }
240
- }
241
- FirestoreClient.instance = null;
242
- /**
243
- * Firestore error class
244
- */
245
- export class FirestoreError extends Error {
246
- constructor(message, code, details) {
247
- super(message);
248
- this.code = code;
249
- this.details = details;
250
- this.name = 'FirestoreError';
251
- }
252
- }
253
- /**
254
- * Error codes for Firestore operations
255
- */
256
- export const FirestoreErrorCode = {
257
- NOT_CONFIGURED: 'NOT_CONFIGURED',
258
- NETWORK_ERROR: 'NETWORK_ERROR',
259
- NOT_FOUND: 'NOT_FOUND',
260
- PERMISSION_DENIED: 'PERMISSION_DENIED',
261
- INVALID_DOCUMENT: 'INVALID_DOCUMENT',
262
- CACHE_ERROR: 'CACHE_ERROR',
263
- };
264
- //# sourceMappingURL=firestore-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"firestore-client.js","sourceRoot":"","sources":["../../../src/firestore/firestore-client.ts"],"names":[],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Firestore Module
3
- *
4
- * Provides Firestore-based update checking for the native-update plugin.
5
- * Uses Google's Firebase Firestore free tier for storing update manifests.
6
- */
7
- export type { FirestoreTimestamp, ManifestDocument, ManifestCurrentVersion, ManifestDelta, ManifestPreviousVersion, RolloutConfig, RolloutTargetSegments, RolloutSchedule, AppDocument, ChannelConfig, BuildDocument, FileManifestEntry, DeltaDocument, AnalyticsBatchDocument, ErrorSample, DeviceInfo, UpdateCheckResponse, FirestoreConfig, } from './schema';
8
- export { COLLECTIONS, getManifestId, getDeltaId, isValidVersion, isValidChecksum, timestampToDate, dateToTimestamp, } from './schema';
9
- export { FirestoreClient, FirestoreError, FirestoreErrorCode, } from './firestore-client';
10
- export type { ManifestReaderOptions } from './manifest-reader';
11
- export { ManifestReader, createManifestReader } from './manifest-reader';
@@ -1,11 +0,0 @@
1
- /**
2
- * Firestore Module
3
- *
4
- * Provides Firestore-based update checking for the native-update plugin.
5
- * Uses Google's Firebase Firestore free tier for storing update manifests.
6
- */
7
- export { COLLECTIONS, getManifestId, getDeltaId, isValidVersion, isValidChecksum, timestampToDate, dateToTimestamp, } from './schema';
8
- // Firestore client
9
- export { FirestoreClient, FirestoreError, FirestoreErrorCode, } from './firestore-client';
10
- export { ManifestReader, createManifestReader } from './manifest-reader';
11
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/firestore/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAwBH,OAAO,EACL,WAAW,EACX,aAAa,EACb,UAAU,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,GAChB,MAAM,UAAU,CAAC;AAElB,mBAAmB;AACnB,OAAO,EACL,eAAe,EACf,cAAc,EACd,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,87 +0,0 @@
1
- /**
2
- * Manifest Reader
3
- *
4
- * High-level interface for reading update manifests from Firestore
5
- * with rollout eligibility checking and delta update support.
6
- */
7
- import type { ManifestDocument, DeviceInfo, UpdateCheckResponse, RolloutConfig } from './schema';
8
- import { FirestoreClient } from './firestore-client';
9
- /**
10
- * Manifest reader options
11
- */
12
- export interface ManifestReaderOptions {
13
- /** Current app version for comparison */
14
- currentVersion: string;
15
- /** Device information for rollout eligibility */
16
- deviceInfo: DeviceInfo;
17
- /** Whether to check delta availability */
18
- checkDeltas?: boolean;
19
- /** Force refresh (bypass cache) */
20
- forceRefresh?: boolean;
21
- }
22
- /**
23
- * Manifest Reader class
24
- */
25
- export declare class ManifestReader {
26
- private readonly firestoreClient;
27
- private readonly logger;
28
- constructor(firestoreClient: FirestoreClient);
29
- /**
30
- * Check for updates
31
- */
32
- checkForUpdates(options: ManifestReaderOptions): Promise<UpdateCheckResponse>;
33
- /**
34
- * Check rollout eligibility for a device
35
- */
36
- checkRolloutEligibility(rollout: RolloutConfig, deviceInfo: DeviceInfo): Promise<{
37
- eligible: boolean;
38
- reason: string;
39
- }>;
40
- /**
41
- * Check target segments eligibility
42
- */
43
- private checkSegments;
44
- /**
45
- * Calculate current percentage for gradual rollout
46
- */
47
- private calculateGradualPercentage;
48
- /**
49
- * Get deterministic percentile for a device ID
50
- * Uses SHA-256 hash for uniform distribution
51
- */
52
- private getDevicePercentile;
53
- /**
54
- * Hash a string using SHA-256
55
- */
56
- private hashString;
57
- /**
58
- * Convert hash to percentile (0-100)
59
- * Takes first 8 hex chars and maps to percentage
60
- */
61
- private hashToPercentile;
62
- /**
63
- * Compare two semantic versions
64
- * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
65
- */
66
- private compareVersions;
67
- /**
68
- * Check if v2 is newer than v1
69
- */
70
- private isNewerVersion;
71
- /**
72
- * Get raw manifest document
73
- */
74
- getManifest(): Promise<ManifestDocument | null>;
75
- /**
76
- * Get manifest for specific app and channel
77
- */
78
- getManifestFor(appId: string, channel: string): Promise<ManifestDocument | null>;
79
- /**
80
- * Clear cache
81
- */
82
- clearCache(): void;
83
- }
84
- /**
85
- * Create ManifestReader instance
86
- */
87
- export declare function createManifestReader(firestoreClient: FirestoreClient): ManifestReader;
@@ -1,294 +0,0 @@
1
- /**
2
- * Manifest Reader
3
- *
4
- * High-level interface for reading update manifests from Firestore
5
- * with rollout eligibility checking and delta update support.
6
- */
7
- import { timestampToDate } from './schema';
8
- import { Logger } from '../core/logger';
9
- /**
10
- * Manifest Reader class
11
- */
12
- export class ManifestReader {
13
- constructor(firestoreClient) {
14
- this.firestoreClient = firestoreClient;
15
- this.logger = Logger.getInstance();
16
- }
17
- /**
18
- * Check for updates
19
- */
20
- async checkForUpdates(options) {
21
- const { currentVersion, deviceInfo, checkDeltas = true } = options;
22
- try {
23
- // Clear cache if forced refresh
24
- if (options.forceRefresh) {
25
- this.firestoreClient.clearCache();
26
- }
27
- // Get manifest from Firestore
28
- const manifest = await this.firestoreClient.getManifest();
29
- if (!manifest) {
30
- this.logger.debug('No manifest found');
31
- return { updateAvailable: false };
32
- }
33
- // Check if update is available
34
- const updateAvailable = this.isNewerVersion(currentVersion, manifest.current.version);
35
- if (!updateAvailable) {
36
- return {
37
- updateAvailable: false,
38
- version: manifest.current.version,
39
- };
40
- }
41
- // Check rollout eligibility
42
- const rolloutCheck = await this.checkRolloutEligibility(manifest.rollout, deviceInfo);
43
- if (!rolloutCheck.eligible) {
44
- return {
45
- updateAvailable: true,
46
- version: manifest.current.version,
47
- rolloutEligible: false,
48
- rolloutReason: rolloutCheck.reason,
49
- };
50
- }
51
- // Build response
52
- const response = {
53
- updateAvailable: true,
54
- version: manifest.current.version,
55
- bundleUrl: manifest.current.bundleUrl,
56
- minNativeVersion: manifest.current.minNativeVersion,
57
- releaseNotes: manifest.current.releaseNotes,
58
- signature: manifest.current.signature,
59
- checksum: manifest.current.checksum,
60
- mandatory: manifest.current.mandatory,
61
- size: manifest.current.size,
62
- rolloutEligible: true,
63
- };
64
- // Check for delta availability
65
- if (checkDeltas && manifest.deltas) {
66
- const delta = manifest.deltas[currentVersion];
67
- if (delta) {
68
- response.delta = {
69
- available: true,
70
- patchUrl: delta.patchUrl,
71
- patchSize: delta.patchSize,
72
- patchChecksum: delta.patchChecksum,
73
- targetChecksum: delta.targetChecksum,
74
- };
75
- this.logger.debug('Delta update available', {
76
- from: currentVersion,
77
- to: manifest.current.version,
78
- patchSize: delta.patchSize,
79
- });
80
- }
81
- else {
82
- response.delta = { available: false };
83
- }
84
- }
85
- return response;
86
- }
87
- catch (error) {
88
- this.logger.error('Error checking for updates', error);
89
- throw error;
90
- }
91
- }
92
- /**
93
- * Check rollout eligibility for a device
94
- */
95
- async checkRolloutEligibility(rollout, deviceInfo) {
96
- var _a, _b;
97
- // Check if rollout is enabled
98
- if (!rollout.enabled) {
99
- return { eligible: true, reason: 'Rollout not enabled, all devices eligible' };
100
- }
101
- // Check time window
102
- const now = Date.now();
103
- const startTime = timestampToDate(rollout.startTime).getTime();
104
- if (now < startTime) {
105
- return { eligible: false, reason: 'Rollout not started yet' };
106
- }
107
- if (rollout.endTime) {
108
- const endTime = timestampToDate(rollout.endTime).getTime();
109
- if (now > endTime) {
110
- return { eligible: false, reason: 'Rollout ended' };
111
- }
112
- }
113
- // Check scheduled rollout
114
- if (((_a = rollout.schedule) === null || _a === void 0 ? void 0 : _a.type) === 'scheduled' && rollout.schedule.scheduledTime) {
115
- const scheduledTime = timestampToDate(rollout.schedule.scheduledTime).getTime();
116
- if (now < scheduledTime) {
117
- return { eligible: false, reason: 'Scheduled for later' };
118
- }
119
- }
120
- // Check target segments
121
- if (rollout.targetSegments) {
122
- const segmentCheck = this.checkSegments(rollout.targetSegments, deviceInfo);
123
- if (!segmentCheck.eligible) {
124
- return segmentCheck;
125
- }
126
- }
127
- // Calculate current rollout percentage
128
- let currentPercentage = rollout.percentage;
129
- if (((_b = rollout.schedule) === null || _b === void 0 ? void 0 : _b.type) === 'gradual') {
130
- currentPercentage = this.calculateGradualPercentage(rollout);
131
- }
132
- // Check percentage-based eligibility using deterministic hashing
133
- const devicePercentile = await this.getDevicePercentile(deviceInfo.deviceId);
134
- if (devicePercentile > currentPercentage) {
135
- return {
136
- eligible: false,
137
- reason: `Device percentile ${devicePercentile.toFixed(1)}% > rollout ${currentPercentage}%`,
138
- };
139
- }
140
- return { eligible: true, reason: 'All checks passed' };
141
- }
142
- /**
143
- * Check target segments eligibility
144
- */
145
- checkSegments(segments, deviceInfo) {
146
- // Platform check
147
- if (segments.platforms && segments.platforms.length > 0) {
148
- if (!segments.platforms.includes(deviceInfo.platform)) {
149
- return {
150
- eligible: false,
151
- reason: `Platform ${deviceInfo.platform} not targeted`,
152
- };
153
- }
154
- }
155
- // App version checks
156
- if (segments.minAppVersion) {
157
- if (this.compareVersions(deviceInfo.appVersion, segments.minAppVersion) < 0) {
158
- return {
159
- eligible: false,
160
- reason: `App version below minimum ${segments.minAppVersion}`,
161
- };
162
- }
163
- }
164
- if (segments.maxAppVersion) {
165
- if (this.compareVersions(deviceInfo.appVersion, segments.maxAppVersion) > 0) {
166
- return {
167
- eligible: false,
168
- reason: `App version above maximum ${segments.maxAppVersion}`,
169
- };
170
- }
171
- }
172
- // Device ID whitelist
173
- if (segments.deviceIds && segments.deviceIds.length > 0) {
174
- if (!segments.deviceIds.includes(deviceInfo.deviceId)) {
175
- return { eligible: false, reason: 'Device not in whitelist' };
176
- }
177
- }
178
- // Region check
179
- if (segments.regions && segments.regions.length > 0) {
180
- if (!deviceInfo.region || !segments.regions.includes(deviceInfo.region)) {
181
- return {
182
- eligible: false,
183
- reason: `Region ${deviceInfo.region || 'unknown'} not targeted`,
184
- };
185
- }
186
- }
187
- return { eligible: true, reason: 'Segment checks passed' };
188
- }
189
- /**
190
- * Calculate current percentage for gradual rollout
191
- */
192
- calculateGradualPercentage(rollout) {
193
- var _a, _b;
194
- if (!((_a = rollout.schedule) === null || _a === void 0 ? void 0 : _a.gradualSteps) || !((_b = rollout.schedule) === null || _b === void 0 ? void 0 : _b.gradualInterval)) {
195
- return rollout.percentage;
196
- }
197
- const startTime = timestampToDate(rollout.startTime).getTime();
198
- const elapsedHours = (Date.now() - startTime) / (1000 * 60 * 60);
199
- const intervalHours = rollout.schedule.gradualInterval;
200
- const stepIndex = Math.floor(elapsedHours / intervalHours);
201
- const steps = rollout.schedule.gradualSteps;
202
- if (stepIndex >= steps.length) {
203
- return steps[steps.length - 1];
204
- }
205
- return steps[stepIndex];
206
- }
207
- /**
208
- * Get deterministic percentile for a device ID
209
- * Uses SHA-256 hash for uniform distribution
210
- */
211
- async getDevicePercentile(deviceId) {
212
- const hash = await this.hashString(deviceId);
213
- return this.hashToPercentile(hash);
214
- }
215
- /**
216
- * Hash a string using SHA-256
217
- */
218
- async hashString(input) {
219
- const encoder = new TextEncoder();
220
- const data = encoder.encode(input);
221
- // Use Web Crypto API
222
- const hashBuffer = await crypto.subtle.digest('SHA-256', data);
223
- const hashArray = Array.from(new Uint8Array(hashBuffer));
224
- return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
225
- }
226
- /**
227
- * Convert hash to percentile (0-100)
228
- * Takes first 8 hex chars and maps to percentage
229
- */
230
- hashToPercentile(hash) {
231
- const hashInt = parseInt(hash.substring(0, 8), 16);
232
- const maxInt = parseInt('ffffffff', 16);
233
- return (hashInt / maxInt) * 100;
234
- }
235
- /**
236
- * Compare two semantic versions
237
- * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
238
- */
239
- compareVersions(v1, v2) {
240
- // Remove pre-release suffix for comparison
241
- const cleanV1 = v1.split('-')[0];
242
- const cleanV2 = v2.split('-')[0];
243
- const parts1 = cleanV1.split('.').map(Number);
244
- const parts2 = cleanV2.split('.').map(Number);
245
- for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
246
- const p1 = parts1[i] || 0;
247
- const p2 = parts2[i] || 0;
248
- if (p1 > p2)
249
- return 1;
250
- if (p1 < p2)
251
- return -1;
252
- }
253
- // If versions are equal, check pre-release
254
- // Pre-release versions are lower than release versions
255
- const hasPreV1 = v1.includes('-');
256
- const hasPreV2 = v2.includes('-');
257
- if (hasPreV1 && !hasPreV2)
258
- return -1;
259
- if (!hasPreV1 && hasPreV2)
260
- return 1;
261
- return 0;
262
- }
263
- /**
264
- * Check if v2 is newer than v1
265
- */
266
- isNewerVersion(v1, v2) {
267
- return this.compareVersions(v1, v2) < 0;
268
- }
269
- /**
270
- * Get raw manifest document
271
- */
272
- async getManifest() {
273
- return this.firestoreClient.getManifest();
274
- }
275
- /**
276
- * Get manifest for specific app and channel
277
- */
278
- async getManifestFor(appId, channel) {
279
- return this.firestoreClient.getManifestFor(appId, channel);
280
- }
281
- /**
282
- * Clear cache
283
- */
284
- clearCache() {
285
- this.firestoreClient.clearCache();
286
- }
287
- }
288
- /**
289
- * Create ManifestReader instance
290
- */
291
- export function createManifestReader(firestoreClient) {
292
- return new ManifestReader(firestoreClient);
293
- }
294
- //# sourceMappingURL=manifest-reader.js.map