native-update 1.4.9 → 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.
- package/Readme.md +35 -9
- package/android/manifest-additions.xml +28 -0
- package/android/src/main/AndroidManifest.xml +3 -7
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundNotificationManager.kt +21 -13
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdatePlugin.kt +15 -0
- package/android/src/main/java/com/aoneahsan/nativeupdate/BackgroundUpdateWorker.kt +23 -7
- package/android/src/main/java/com/aoneahsan/nativeupdate/LiveUpdatePlugin.kt +346 -31
- package/android/src/main/java/com/aoneahsan/nativeupdate/NativeUpdatePlugin.kt +32 -34
- package/android/src/main/java/com/aoneahsan/nativeupdate/NotificationActionReceiver.kt +10 -1
- package/android/src/main/java/com/aoneahsan/nativeupdate/SecurityManager.kt +18 -18
- package/cli/AGENTS.md +43 -0
- package/cli/CLAUDE.md +65 -0
- package/cli/commands/backend-create.js +56 -15
- package/cli/commands/bundle-create.js +39 -7
- package/cli/commands/monitor.js +72 -51
- package/cli/index.js +10 -24
- package/cli/package.json +11 -3
- package/dist/esm/app-review/app-review-manager.js +0 -1
- package/dist/esm/app-review/index.js +0 -1
- package/dist/esm/app-review/platform-review-handler.js +0 -1
- package/dist/esm/app-review/review-conditions-checker.js +0 -1
- package/dist/esm/app-review/review-rate-limiter.js +0 -1
- package/dist/esm/app-review/types.js +0 -1
- package/dist/esm/app-update/app-update-checker.js +0 -1
- package/dist/esm/app-update/app-update-installer.d.ts +1 -0
- package/dist/esm/app-update/app-update-installer.js +19 -8
- package/dist/esm/app-update/app-update-manager.js +0 -1
- package/dist/esm/app-update/app-update-notifier.js +0 -1
- package/dist/esm/app-update/index.js +0 -1
- package/dist/esm/app-update/platform-app-update.js +12 -3
- package/dist/esm/app-update/types.js +0 -1
- package/dist/esm/background-update/background-scheduler.js +0 -1
- package/dist/esm/background-update/index.js +0 -1
- package/dist/esm/background-update/notification-manager.js +0 -1
- package/dist/esm/config/support.js +0 -1
- package/dist/esm/core/analytics.d.ts +13 -0
- package/dist/esm/core/analytics.js +15 -1
- package/dist/esm/core/cache-manager.js +0 -1
- package/dist/esm/core/config.d.ts +6 -30
- package/dist/esm/core/config.js +1 -8
- package/dist/esm/core/errors.d.ts +1 -0
- package/dist/esm/core/errors.js +1 -1
- package/dist/esm/core/event-emitter.d.ts +0 -3
- package/dist/esm/core/event-emitter.js +8 -3
- package/dist/esm/core/logger.js +0 -1
- package/dist/esm/core/performance.js +0 -1
- package/dist/esm/core/plugin-manager.js +3 -1
- package/dist/esm/core/security.d.ts +22 -3
- package/dist/esm/core/security.js +46 -7
- package/dist/esm/definitions.d.ts +13 -40
- package/dist/esm/definitions.js +0 -1
- package/dist/esm/index.d.ts +3 -4
- package/dist/esm/index.js +3 -3
- package/dist/esm/live-update/bundle-manager.d.ts +8 -0
- package/dist/esm/live-update/bundle-manager.js +20 -1
- package/dist/esm/live-update/certificate-pinning.js +0 -1
- package/dist/esm/live-update/delta-processor.d.ts +1 -1
- package/dist/esm/live-update/delta-processor.js +3 -1
- package/dist/esm/live-update/download-manager.d.ts +36 -5
- package/dist/esm/live-update/download-manager.js +70 -24
- package/dist/esm/live-update/rollout-checker.d.ts +1 -1
- package/dist/esm/live-update/rollout-checker.js +5 -6
- package/dist/esm/live-update/update-manager.d.ts +12 -1
- package/dist/esm/live-update/update-manager.js +38 -11
- package/dist/esm/live-update/version-manager.d.ts +9 -12
- package/dist/esm/live-update/version-manager.js +40 -68
- package/dist/esm/plugin.js +82 -89
- package/dist/esm/security/crypto.js +11 -7
- package/dist/esm/security/validator.js +0 -1
- package/dist/esm/types/rollout.d.ts +85 -0
- package/dist/esm/types/rollout.js +25 -0
- package/dist/esm/web.d.ts +26 -1
- package/dist/esm/web.js +214 -75
- package/dist/plugin.cjs.js +1 -2
- package/dist/plugin.esm.js +1 -2
- package/dist/plugin.js +2 -3
- package/docs/AGENTS.md +38 -0
- package/docs/CHANGELOG.md +275 -0
- package/docs/CLAUDE.md +101 -0
- package/docs/MANUAL-TASKS.md +17 -0
- package/docs/MARKETING_WEBSITE_TRACKER.md +18 -2
- package/docs/MIGRATION.md +170 -0
- package/docs/PACKAGES.md +167 -0
- package/docs/PERFORMANCE.md +110 -0
- package/docs/PROJECT_COMPLETION_TRACKER.md +4 -35
- package/docs/README.md +12 -2
- package/docs/REMAINING_FEATURES.md +123 -76
- package/docs/ROADMAP.md +200 -120
- package/docs/SECURITY-IF-REPO-PUBLIC.md +232 -0
- package/docs/TESTING_REQUIREMENTS.md +1 -112
- package/docs/ai-knowledge-base/00-project-profile.md +38 -0
- package/docs/ai-knowledge-base/01-features.md +46 -0
- package/docs/ai-knowledge-base/02-routes.md +72 -0
- package/docs/ai-knowledge-base/03-tech-stack.md +57 -0
- package/docs/ai-knowledge-base/README.md +23 -0
- package/docs/analytics-tracking.md +37 -0
- package/docs/capacitor-official-plugins.md +46 -0
- package/docs/capawesome-plugins.md +29 -0
- package/docs/deployment/HOSTINGER_DEPLOY.md +370 -0
- package/docs/deployment/PRODUCTION-DEPLOY-CHECKLIST.md +184 -0
- package/docs/docs-site/plan.md +201 -0
- package/docs/docs-site/scope.md +127 -0
- package/docs/docs-site/tracker.json +235 -0
- package/docs/error-handling-tracking.md +37 -0
- package/docs/features/laravel-nova-backend/ASSESSMENT-SUMMARY.md +96 -0
- package/docs/features/laravel-nova-backend/IMPLEMENTATION-PLAN.md +504 -0
- package/docs/features/laravel-nova-backend/progress-tracker.json +184 -0
- package/docs/guides/testing-guide.md +15 -41
- package/docs/package-audit.md +41 -0
- package/docs/play-store/ASO-METADATA.md +5 -0
- package/docs/play-store/DATA-SAFETY.md +5 -0
- package/docs/play-store/DECLARATIONS.md +5 -0
- package/docs/play-store/README.md +27 -0
- package/docs/play-store/RELEASE-NOTES.md +99 -0
- package/docs/play-store/RELEASE-STEPS.md +6 -0
- package/docs/play-store/STORE-LISTING.md +7 -0
- package/docs/play-store/SUBMISSION-CHECKLIST.md +5 -0
- package/docs/production-readiness.md +1 -1
- package/docs/project-audit/2026-05-16/00-FINALIZATION-PLAN.md +123 -0
- package/docs/project-audit/2026-05-16/01-BATCH-PLAN.md +227 -0
- package/docs/project-audit/2026-05-16/02-AUDIT-FINDINGS.md +144 -0
- package/docs/project-audit/2026-05-16/sessions/batch-01.md +42 -0
- package/docs/project-audit/2026-05-16/sessions/batch-02.md +74 -0
- package/docs/project-audit/2026-05-16/sessions/batch-03.md +71 -0
- package/docs/project-audit/2026-05-16/sessions/batch-04.md +88 -0
- package/docs/project-audit/2026-05-16/sessions/batch-05.md +63 -0
- package/docs/project-audit/2026-05-16/sessions/batch-06.md +103 -0
- package/docs/project-audit/2026-05-16/sessions/batch-07.md +61 -0
- package/docs/project-audit/2026-05-16/sessions/batch-08.md +101 -0
- package/docs/project-audit/2026-05-16/sessions/batch-09.md +105 -0
- package/docs/project-audit/2026-05-16/sessions/batch-10.md +102 -0
- package/docs/project-audit/AUDIT-HISTORY.md +74 -0
- package/docs/project-audit/BATCH-PLAN.md +168 -0
- package/docs/project-audit/MARKETING-WEBSITE-FINDINGS-2026-05-11.md +73 -0
- package/docs/project-audit/PRODUCTION-READINESS-AUDIT-2026-05-08.md +275 -0
- package/docs/project-finalization/00-tracker.json +60 -0
- package/docs/project-knowledge-base/01-system-overview.md +227 -0
- package/docs/project-knowledge-base/02-routes-pages-forms-users.md +352 -0
- package/docs/project-knowledge-base/03-tech-stack-modules-services.md +379 -0
- package/docs/project-knowledge-base/04-data-models-integrations.md +244 -0
- package/docs/project-knowledge-base/05-docs-corpus-inventory.md +256 -0
- package/docs/project-knowledge-base/06-operations-testing-legal-content.md +208 -0
- package/docs/project-knowledge-base/README.md +103 -0
- package/docs/project-profiles/native-update-capacitor-update-platform-project-profile-last-updated-2026-05-19.md +81 -0
- package/docs/rules-tracker.md +102 -0
- package/docs/security/PRE-LAUNCH-PENTEST-CHECKLIST.md +116 -0
- package/docs/seo-aeo-rules.json +3043 -0
- package/docs/social-media-marketing/README.md +81 -0
- package/docs/social-media-marketing/posts-batch-01.md +613 -0
- package/docs/social-media-marketing/posts-batch-02.md +528 -0
- package/docs/social-media-marketing/whatsapp-messages-batch-01.md +458 -0
- package/docs/social-media-marketing/whatsapp-status-batch-01.md +355 -0
- package/docs/tracking/finalization-2026-05-16-tracker.json +346 -0
- package/docs/tracking/full-audit-tracker.json +121 -0
- package/docs/tracking/production-readiness-audit-tracker.json +429 -0
- package/docs/tracking/seo-checklist-tracker.json +333 -0
- package/ios/Plugin/BackgroundUpdate/BackgroundUpdatePlugin.swift +66 -9
- package/ios/Plugin/LiveUpdate/LiveUpdatePlugin.swift +306 -52
- package/ios/Plugin/NativeUpdatePlugin.swift +22 -9
- package/ios/Plugin/Security/SecurityManager.swift +13 -14
- package/package.json +37 -38
- package/cli/node_modules/.yarn-integrity +0 -16
- package/cli/node_modules/commander/LICENSE +0 -22
- package/cli/node_modules/commander/Readme.md +0 -1148
- package/cli/node_modules/commander/esm.mjs +0 -16
- package/cli/node_modules/commander/index.js +0 -26
- package/cli/node_modules/commander/lib/argument.js +0 -145
- package/cli/node_modules/commander/lib/command.js +0 -2179
- package/cli/node_modules/commander/lib/error.js +0 -43
- package/cli/node_modules/commander/lib/help.js +0 -462
- package/cli/node_modules/commander/lib/option.js +0 -329
- package/cli/node_modules/commander/lib/suggestSimilar.js +0 -100
- package/cli/node_modules/commander/package-support.json +0 -16
- package/cli/node_modules/commander/package.json +0 -80
- package/cli/node_modules/commander/typings/esm.d.mts +0 -3
- package/cli/node_modules/commander/typings/index.d.ts +0 -884
- package/cli/yarn.lock +0 -8
- package/dist/esm/__tests__/bundle-manager.test.d.ts +0 -1
- package/dist/esm/__tests__/bundle-manager.test.js +0 -151
- package/dist/esm/__tests__/bundle-manager.test.js.map +0 -1
- package/dist/esm/__tests__/config.test.d.ts +0 -1
- package/dist/esm/__tests__/config.test.js +0 -70
- package/dist/esm/__tests__/config.test.js.map +0 -1
- package/dist/esm/__tests__/delta-processor.test.d.ts +0 -1
- package/dist/esm/__tests__/delta-processor.test.js +0 -77
- package/dist/esm/__tests__/delta-processor.test.js.map +0 -1
- package/dist/esm/__tests__/firestore-schema.test.d.ts +0 -1
- package/dist/esm/__tests__/firestore-schema.test.js +0 -74
- package/dist/esm/__tests__/firestore-schema.test.js.map +0 -1
- package/dist/esm/__tests__/integration.test.d.ts +0 -1
- package/dist/esm/__tests__/integration.test.js +0 -78
- package/dist/esm/__tests__/integration.test.js.map +0 -1
- package/dist/esm/__tests__/manifest-reader.test.d.ts +0 -1
- package/dist/esm/__tests__/manifest-reader.test.js +0 -271
- package/dist/esm/__tests__/manifest-reader.test.js.map +0 -1
- package/dist/esm/__tests__/rollout-checker.test.d.ts +0 -1
- package/dist/esm/__tests__/rollout-checker.test.js +0 -210
- package/dist/esm/__tests__/rollout-checker.test.js.map +0 -1
- package/dist/esm/__tests__/security.test.d.ts +0 -1
- package/dist/esm/__tests__/security.test.js +0 -54
- package/dist/esm/__tests__/security.test.js.map +0 -1
- package/dist/esm/__tests__/version-manager.test.d.ts +0 -1
- package/dist/esm/__tests__/version-manager.test.js +0 -45
- package/dist/esm/__tests__/version-manager.test.js.map +0 -1
- package/dist/esm/app-review/app-review-manager.js.map +0 -1
- package/dist/esm/app-review/index.js.map +0 -1
- package/dist/esm/app-review/platform-review-handler.js.map +0 -1
- package/dist/esm/app-review/review-conditions-checker.js.map +0 -1
- package/dist/esm/app-review/review-rate-limiter.js.map +0 -1
- package/dist/esm/app-review/types.js.map +0 -1
- package/dist/esm/app-update/app-update-checker.js.map +0 -1
- package/dist/esm/app-update/app-update-installer.js.map +0 -1
- package/dist/esm/app-update/app-update-manager.js.map +0 -1
- package/dist/esm/app-update/app-update-notifier.js.map +0 -1
- package/dist/esm/app-update/index.js.map +0 -1
- package/dist/esm/app-update/platform-app-update.js.map +0 -1
- package/dist/esm/app-update/types.js.map +0 -1
- package/dist/esm/background-update/background-scheduler.js.map +0 -1
- package/dist/esm/background-update/index.js.map +0 -1
- package/dist/esm/background-update/notification-manager.js.map +0 -1
- package/dist/esm/config/support.js.map +0 -1
- package/dist/esm/core/analytics.js.map +0 -1
- package/dist/esm/core/cache-manager.js.map +0 -1
- package/dist/esm/core/config.js.map +0 -1
- package/dist/esm/core/errors.js.map +0 -1
- package/dist/esm/core/event-emitter.js.map +0 -1
- package/dist/esm/core/logger.js.map +0 -1
- package/dist/esm/core/performance.js.map +0 -1
- package/dist/esm/core/plugin-manager.js.map +0 -1
- package/dist/esm/core/security.js.map +0 -1
- package/dist/esm/definitions.js.map +0 -1
- package/dist/esm/firestore/firestore-client.d.ts +0 -109
- package/dist/esm/firestore/firestore-client.js +0 -264
- package/dist/esm/firestore/firestore-client.js.map +0 -1
- package/dist/esm/firestore/index.d.ts +0 -11
- package/dist/esm/firestore/index.js +0 -11
- package/dist/esm/firestore/index.js.map +0 -1
- package/dist/esm/firestore/manifest-reader.d.ts +0 -87
- package/dist/esm/firestore/manifest-reader.js +0 -294
- package/dist/esm/firestore/manifest-reader.js.map +0 -1
- package/dist/esm/firestore/schema.d.ts +0 -507
- package/dist/esm/firestore/schema.js +0 -73
- package/dist/esm/firestore/schema.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/live-update/bundle-manager.js.map +0 -1
- package/dist/esm/live-update/certificate-pinning.js.map +0 -1
- package/dist/esm/live-update/delta-processor.js.map +0 -1
- package/dist/esm/live-update/download-manager.js.map +0 -1
- package/dist/esm/live-update/rollout-checker.js.map +0 -1
- package/dist/esm/live-update/update-manager.js.map +0 -1
- package/dist/esm/live-update/version-manager.js.map +0 -1
- package/dist/esm/plugin.js.map +0 -1
- package/dist/esm/security/crypto.js.map +0 -1
- package/dist/esm/security/validator.js.map +0 -1
- package/dist/esm/web.js.map +0 -1
- package/dist/plugin.cjs.js.map +0 -1
- package/dist/plugin.esm.js.map +0 -1
- package/dist/plugin.js.map +0 -1
- package/docs/FIREBASE_INTEGRATION_TRACKER.md +0 -321
- package/docs/FIREBASE_QUERIES_AND_INDEXES_AUDIT.md +0 -221
- package/docs/examples/firebase-backend-example.md +0 -27
- package/docs/guides/no-cost-backend-implementation-plan.md +0 -77
- package/docs/guides/no-cost-firestore-google-drive-backend.md +0 -60
- package/docs/play-console-rejection-rules.json +0 -428
- /package/docs/{MARKETING_WEBSITE_PLAN.md → archive/MARKETING_WEBSITE_PLAN.md} +0 -0
package/cli/AGENTS.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# AGENTS.md - CLI Tool
|
|
2
|
+
|
|
3
|
+
Agent instructions for the native-update CLI tool.
|
|
4
|
+
|
|
5
|
+
## 🔴 3-Day Freshness Rule
|
|
6
|
+
Check and update this file at least every 3 days. See root AGENTS.md.
|
|
7
|
+
|
|
8
|
+
## Package Manager Hierarchy: nvm → npm (global) → yarn (local) (IRON-SOLID)
|
|
9
|
+
|
|
10
|
+
Three tiers, each tool ONLY for its tier — for the best, most reproducible dev results:
|
|
11
|
+
- **`nvm`** → install/update Node.js (which bundles `npm`): `nvm install --lts`. Use nvm to get/update `npm` itself.
|
|
12
|
+
- **`npm`** → ALL global packages: `npm install -g yarn` (install yarn globally if missing) + `npm install -g <pkg>` (every other global CLI).
|
|
13
|
+
- **`yarn`** → ALL local project work: `yarn`, `yarn add <pkg>`, `yarn add -D <pkg>` inside the project.
|
|
14
|
+
|
|
15
|
+
❌ NEVER use `npm`/`pnpm` for LOCAL installs. NEVER use `pnpm` at all. ✅ Only `yarn.lock` in the project — delete `package-lock.json` and `pnpm-lock.yaml`.
|
|
16
|
+
|
|
17
|
+
## Scope
|
|
18
|
+
|
|
19
|
+
Node.js CLI for release management, bundle operations, and configuration. Distributed as part of the npm package.
|
|
20
|
+
|
|
21
|
+
## Key Rules
|
|
22
|
+
|
|
23
|
+
1. **ESM module**: Uses `"type": "module"` — all imports must use ESM syntax
|
|
24
|
+
2. **Interactive prompts**: Use `prompts` library for user input
|
|
25
|
+
3. **Error messages**: Clear, actionable error messages without exposing internals
|
|
26
|
+
4. **Exit codes**: Use proper exit codes (0 success, 1 error)
|
|
27
|
+
5. **Help text**: Every command must have `--help` documentation
|
|
28
|
+
|
|
29
|
+
## When Adding CLI Commands
|
|
30
|
+
|
|
31
|
+
1. Create command file in `commands/`
|
|
32
|
+
2. Register in `index.js`
|
|
33
|
+
3. Update `docs/CLI_REFERENCE.md`
|
|
34
|
+
4. Add usage example to relevant docs
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Gitignore Hygiene (IRON-SOLID)
|
|
39
|
+
`.gitignore` stays current with the project structure — ignore only recoverable artifacts (build/`dist`/`www`/`node_modules`/logs/caches/IDE), never lose source. Custom rules always present: `*.ignore.*`, `project-record-ignore/`. This is a **PRIVATE** repo -> `.env`/secrets/keystores ARE tracked in git. Capacitor: track `android`/`ios` source, ignore native build.
|
|
40
|
+
Full rule + private/public protocol: `~/.claude/rules/project-config.md`.
|
|
41
|
+
Gitignore Last Verified: 2026-06-24
|
|
42
|
+
|
|
43
|
+
**Last Updated**: 2026-04-25
|
package/cli/CLAUDE.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Native Update - CLI
|
|
2
|
+
|
|
3
|
+
Command-line interface for native-update release management and bundle operations.
|
|
4
|
+
|
|
5
|
+
## 🔴 3-Day Freshness Rule
|
|
6
|
+
Check and update this file at least every 3 days. See root CLAUDE.md.
|
|
7
|
+
|
|
8
|
+
## Package Manager Hierarchy: nvm → npm (global) → yarn (local) (IRON-SOLID)
|
|
9
|
+
|
|
10
|
+
Three tiers, each tool ONLY for its tier — for the best, most reproducible dev results:
|
|
11
|
+
- **`nvm`** → install/update Node.js (which bundles `npm`): `nvm install --lts`. Use nvm to get/update `npm` itself.
|
|
12
|
+
- **`npm`** → ALL global packages: `npm install -g yarn` (install yarn globally if missing) + `npm install -g <pkg>` (every other global CLI).
|
|
13
|
+
- **`yarn`** → ALL local project work: `yarn`, `yarn add <pkg>`, `yarn add -D <pkg>` inside the project.
|
|
14
|
+
|
|
15
|
+
❌ NEVER use `npm`/`pnpm` for LOCAL installs. NEVER use `pnpm` at all. ✅ Only `yarn.lock` in the project — delete `package-lock.json` and `pnpm-lock.yaml`.
|
|
16
|
+
|
|
17
|
+
## Structure
|
|
18
|
+
|
|
19
|
+
| File/Folder | Purpose |
|
|
20
|
+
|-------------|---------|
|
|
21
|
+
| `index.js` | CLI entry point (~10KB) |
|
|
22
|
+
| `commands/` | Command implementations |
|
|
23
|
+
| `package.json` | CLI dependencies |
|
|
24
|
+
|
|
25
|
+
## Dependencies
|
|
26
|
+
- `commander` — Argument parsing
|
|
27
|
+
- `chalk` — Colored terminal output
|
|
28
|
+
- `ora` — Loading spinners
|
|
29
|
+
- `archiver` — ZIP creation
|
|
30
|
+
- `prompts` — Interactive prompts
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Via npx
|
|
36
|
+
npx native-update <command>
|
|
37
|
+
|
|
38
|
+
# Or install globally
|
|
39
|
+
npm install -g native-update
|
|
40
|
+
native-update <command>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Commands
|
|
44
|
+
|
|
45
|
+
The CLI provides commands for:
|
|
46
|
+
- Bundle management (create, verify, sign)
|
|
47
|
+
- Update publishing (upload, activate, rollback)
|
|
48
|
+
- Configuration management
|
|
49
|
+
- Release management
|
|
50
|
+
|
|
51
|
+
## Module System
|
|
52
|
+
- ESM (`"type": "module"` in package.json)
|
|
53
|
+
- Uses `commander` for CLI framework
|
|
54
|
+
|
|
55
|
+
## FilesHub Rule (inherited)
|
|
56
|
+
All file storage uses FilesHub API. See root CLAUDE.md.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Gitignore Hygiene (IRON-SOLID)
|
|
61
|
+
`.gitignore` stays current with the project structure — ignore only recoverable artifacts (build/`dist`/`www`/`node_modules`/logs/caches/IDE), never lose source. Custom rules always present: `*.ignore.*`, `project-record-ignore/`. This is a **PRIVATE** repo -> `.env`/secrets/keystores ARE tracked in git. Capacitor: track `android`/`ios` source, ignore native build.
|
|
62
|
+
Full rule + private/public protocol: `~/.claude/rules/project-config.md`.
|
|
63
|
+
Gitignore Last Verified: 2026-06-24
|
|
64
|
+
|
|
65
|
+
**Last Updated**: 2026-04-25
|
|
@@ -8,6 +8,46 @@ import ora from 'ora';
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = dirname(__filename);
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Banner injected at the top of every generated server-side file. The
|
|
13
|
+
* generator emits SCAFFOLDS, not turn-key production code: bundle
|
|
14
|
+
* lookup, persistent storage, signature verification, and rollout
|
|
15
|
+
* gating are all left as `TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]`
|
|
16
|
+
* markers because the right answer depends on the host's storage +
|
|
17
|
+
* DB choices. Fully working references:
|
|
18
|
+
* - example-apps/node-express (minimal HTTP contract)
|
|
19
|
+
* - backend/ (Laravel + Nova production app)
|
|
20
|
+
*/
|
|
21
|
+
const SCAFFOLD_BANNER = `/**
|
|
22
|
+
* ⚠️ SCAFFOLD — IMPLEMENT BEFORE DEPLOYING ⚠️
|
|
23
|
+
*
|
|
24
|
+
* This file was generated by \`native-update backend-create\` as a
|
|
25
|
+
* STARTING POINT, not a deploy-ready service. Every block tagged
|
|
26
|
+
* \`TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]\` MUST be replaced with
|
|
27
|
+
* real persistence + storage + signature verification before this
|
|
28
|
+
* runs in production.
|
|
29
|
+
*
|
|
30
|
+
* Working references:
|
|
31
|
+
* • example-apps/node-express — minimal HTTP-contract reference
|
|
32
|
+
* • backend/ (Laravel + Nova) — full SaaS implementation
|
|
33
|
+
*
|
|
34
|
+
* Deploying this file as-is will respond with hard-coded sample
|
|
35
|
+
* payloads and silently drop uploaded bundles.
|
|
36
|
+
*/
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const POST_GENERATION_WARNING = [
|
|
40
|
+
'',
|
|
41
|
+
chalk.yellow.bold('⚠️ SCAFFOLD — NOT PRODUCTION READY ⚠️'),
|
|
42
|
+
chalk.gray('This template ships with placeholder bundle lookup + storage logic.'),
|
|
43
|
+
chalk.gray('Search the generated code for `TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]`'),
|
|
44
|
+
chalk.gray('and replace each block with your real DB / storage / signing logic.'),
|
|
45
|
+
chalk.gray('See:'),
|
|
46
|
+
chalk.gray(' • example-apps/node-express (minimal HTTP-contract reference)'),
|
|
47
|
+
chalk.gray(' • backend/ (Laravel + Nova) (full SaaS implementation)'),
|
|
48
|
+
'',
|
|
49
|
+
].join('\n');
|
|
50
|
+
|
|
11
51
|
export async function createBackend(type, options) {
|
|
12
52
|
const spinner = ora(`Creating ${type} backend template...`).start();
|
|
13
53
|
|
|
@@ -40,14 +80,15 @@ export async function createBackend(type, options) {
|
|
|
40
80
|
throw new Error(`Unknown backend type: ${type}`);
|
|
41
81
|
}
|
|
42
82
|
|
|
43
|
-
spinner.succeed(`${type} backend created
|
|
44
|
-
|
|
45
|
-
console.log(
|
|
83
|
+
spinner.succeed(`${type} backend scaffold created!`);
|
|
84
|
+
|
|
85
|
+
console.log(POST_GENERATION_WARNING);
|
|
46
86
|
console.log(chalk.bold('Next steps:'));
|
|
47
87
|
console.log(chalk.gray(` 1. cd ${options.output}`));
|
|
48
88
|
console.log(chalk.gray(` 2. npm install`));
|
|
49
89
|
console.log(chalk.gray(` 3. Configure your environment variables`));
|
|
50
|
-
console.log(chalk.gray(` 4.
|
|
90
|
+
console.log(chalk.gray(` 4. Replace every TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY] block`));
|
|
91
|
+
console.log(chalk.gray(` 5. npm run dev`));
|
|
51
92
|
|
|
52
93
|
} catch (error) {
|
|
53
94
|
spinner.fail(`Failed to create backend: ${error.message}`);
|
|
@@ -90,7 +131,7 @@ async function createExpressBackend(outputDir, options) {
|
|
|
90
131
|
);
|
|
91
132
|
|
|
92
133
|
// Create server.js
|
|
93
|
-
const serverCode =
|
|
134
|
+
const serverCode = `${SCAFFOLD_BANNER}import express from 'express';
|
|
94
135
|
import cors from 'cors';
|
|
95
136
|
import dotenv from 'dotenv';
|
|
96
137
|
import { router as bundleRouter } from './routes/bundles.js';
|
|
@@ -141,7 +182,7 @@ router.get('/latest', async (req, res) => {
|
|
|
141
182
|
try {
|
|
142
183
|
const { appId, version, channel = 'production' } = req.query;
|
|
143
184
|
|
|
144
|
-
// TODO:
|
|
185
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: replace with real bundle lookup (DB query against your apps + builds tables)
|
|
145
186
|
// This is a simplified example
|
|
146
187
|
const bundle = {
|
|
147
188
|
version: '1.0.1',
|
|
@@ -173,8 +214,8 @@ router.post('/upload', upload.single('bundle'), async (req, res) => {
|
|
|
173
214
|
const fileBuffer = await fs.readFile(file.path);
|
|
174
215
|
const checksum = crypto.createHash('sha256').update(fileBuffer).digest('hex');
|
|
175
216
|
|
|
176
|
-
// TODO:
|
|
177
|
-
// TODO:
|
|
217
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: persist build metadata (channel, version, checksum, signature, fileshub_public_id) — see backend/ Laravel migrations for the canonical shape
|
|
218
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: upload to FilesHub (preferred) or your CDN; multer drops to /uploads/ which is ephemeral
|
|
178
219
|
|
|
179
220
|
res.json({
|
|
180
221
|
success: true,
|
|
@@ -268,7 +309,7 @@ async function createVercelBackend(outputDir, options) {
|
|
|
268
309
|
);
|
|
269
310
|
|
|
270
311
|
// Create bundles API endpoint
|
|
271
|
-
const bundlesApi =
|
|
312
|
+
const bundlesApi = `${SCAFFOLD_BANNER}export default async function handler(req, res) {
|
|
272
313
|
// Enable CORS
|
|
273
314
|
res.setHeader('Access-Control-Allow-Credentials', true);
|
|
274
315
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
@@ -287,7 +328,7 @@ async function createVercelBackend(outputDir, options) {
|
|
|
287
328
|
// Get latest bundle
|
|
288
329
|
const { appId, version, channel = 'production' } = req.query;
|
|
289
330
|
|
|
290
|
-
// TODO:
|
|
331
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: replace with real bundle lookup against your KV / DB store
|
|
291
332
|
// This is a simplified example
|
|
292
333
|
const bundle = {
|
|
293
334
|
version: '1.0.1',
|
|
@@ -306,8 +347,8 @@ async function createVercelBackend(outputDir, options) {
|
|
|
306
347
|
// Handle bundle upload
|
|
307
348
|
const { version, channel, metadata } = req.body;
|
|
308
349
|
|
|
309
|
-
// TODO:
|
|
310
|
-
// TODO:
|
|
350
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: upload to Vercel Blob / S3 / FilesHub; verify signature against your signing key registry
|
|
351
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: persist build metadata to Vercel KV / Postgres / your DB of choice
|
|
311
352
|
|
|
312
353
|
return res.status(200).json({
|
|
313
354
|
success: true,
|
|
@@ -448,7 +489,7 @@ async function createFirebaseBackend(outputDir, options) {
|
|
|
448
489
|
);
|
|
449
490
|
|
|
450
491
|
// Create index.js
|
|
451
|
-
const indexJs =
|
|
492
|
+
const indexJs = `${SCAFFOLD_BANNER}import { onRequest } from 'firebase-functions/v2/https';
|
|
452
493
|
import * as admin from 'firebase-admin';
|
|
453
494
|
import express from 'express';
|
|
454
495
|
import cors from 'cors';
|
|
@@ -490,8 +531,8 @@ app.post('/api/bundles/upload', async (req, res) => {
|
|
|
490
531
|
try {
|
|
491
532
|
const { version, channel, metadata } = req.body;
|
|
492
533
|
|
|
493
|
-
// TODO:
|
|
494
|
-
// TODO:
|
|
534
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: upload to Cloud Storage; verify signature; enforce monotonic version per channel
|
|
535
|
+
// TODO[SCAFFOLD-IMPLEMENT-BEFORE-DEPLOY]: write to Firestore; remember Firestore rules must be locked down (no public writes)
|
|
495
536
|
|
|
496
537
|
res.json({ success: true, version });
|
|
497
538
|
} catch (error) {
|
|
@@ -3,13 +3,15 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import crypto from 'crypto';
|
|
5
5
|
import archiver from 'archiver';
|
|
6
|
-
import { createWriteStream } from 'fs';
|
|
6
|
+
import { createWriteStream, createReadStream } from 'fs';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import { dirname, join } from 'path';
|
|
9
9
|
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
11
|
const __dirname = dirname(__filename);
|
|
12
12
|
|
|
13
|
+
const NEVER_BUNDLE = ['node_modules', '.git', '.env', '.env.local', '.env.production'];
|
|
14
|
+
|
|
13
15
|
export async function createBundle(webDir, options) {
|
|
14
16
|
console.log(chalk.blue('🔨 Creating update bundle...'));
|
|
15
17
|
|
|
@@ -28,6 +30,18 @@ export async function createBundle(webDir, options) {
|
|
|
28
30
|
throw new Error(`No index.html found in ${webDir}. Is this a valid web build directory?`);
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
// Refuse to bundle a project root by mistake — `node_modules`, `.git`,
|
|
34
|
+
// and `.env*` should never end up in an OTA bundle. Catches the common
|
|
35
|
+
// mistake of pointing at the project root instead of `dist/` or `www/`.
|
|
36
|
+
const entries = await fs.readdir(webDir);
|
|
37
|
+
const dangerous = entries.filter((e) => NEVER_BUNDLE.includes(e));
|
|
38
|
+
if (dangerous.length > 0) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Refusing to bundle: ${webDir} contains ${dangerous.join(', ')}. ` +
|
|
41
|
+
`Point at your built web output (e.g. ./dist or ./www), not the project root.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
31
45
|
// Create output directory
|
|
32
46
|
const outputDir = path.resolve(options.output);
|
|
33
47
|
await fs.mkdir(outputDir, { recursive: true });
|
|
@@ -44,13 +58,24 @@ export async function createBundle(webDir, options) {
|
|
|
44
58
|
}
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
// Parse --metadata separately so we can give a clearer error than
|
|
62
|
+
// a bare "Unexpected token" if the user passes invalid JSON.
|
|
63
|
+
let extraMetadata = {};
|
|
64
|
+
if (options.metadata) {
|
|
65
|
+
try {
|
|
66
|
+
extraMetadata = JSON.parse(options.metadata);
|
|
67
|
+
} catch (e) {
|
|
68
|
+
throw new Error(`Invalid JSON in --metadata: ${e.message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
47
72
|
// Create bundle metadata
|
|
48
73
|
const metadata = {
|
|
49
74
|
version,
|
|
50
75
|
channel: options.channel,
|
|
51
76
|
created: new Date().toISOString(),
|
|
52
77
|
platform: 'web',
|
|
53
|
-
...
|
|
78
|
+
...extraMetadata,
|
|
54
79
|
};
|
|
55
80
|
|
|
56
81
|
const bundleId = `${version}-${Date.now()}`;
|
|
@@ -81,13 +106,20 @@ export async function createBundle(webDir, options) {
|
|
|
81
106
|
await archive.finalize();
|
|
82
107
|
await archivePromise;
|
|
83
108
|
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
const
|
|
109
|
+
// Stream the bundle through the SHA-256 hasher so a 100MB+ bundle
|
|
110
|
+
// doesn't get slurped into RAM all at once. Size comes from fs.stat.
|
|
111
|
+
const bundleStat = await fs.stat(bundlePath);
|
|
112
|
+
const checksum = await new Promise((resolve, reject) => {
|
|
113
|
+
const hash = crypto.createHash('sha256');
|
|
114
|
+
createReadStream(bundlePath)
|
|
115
|
+
.on('data', (chunk) => hash.update(chunk))
|
|
116
|
+
.on('end', () => resolve(hash.digest('hex')))
|
|
117
|
+
.on('error', reject);
|
|
118
|
+
});
|
|
87
119
|
|
|
88
120
|
// Update metadata with file info
|
|
89
121
|
metadata.checksum = checksum;
|
|
90
|
-
metadata.size =
|
|
122
|
+
metadata.size = bundleStat.size;
|
|
91
123
|
metadata.filename = bundleFileName;
|
|
92
124
|
|
|
93
125
|
// Save metadata
|
|
@@ -97,7 +129,7 @@ export async function createBundle(webDir, options) {
|
|
|
97
129
|
console.log('');
|
|
98
130
|
console.log(chalk.bold('Bundle Details:'));
|
|
99
131
|
console.log(chalk.gray(` File: ${bundlePath}`));
|
|
100
|
-
console.log(chalk.gray(` Size: ${(
|
|
132
|
+
console.log(chalk.gray(` Size: ${(bundleStat.size / 1024 / 1024).toFixed(2)} MB`));
|
|
101
133
|
console.log(chalk.gray(` Checksum: ${checksum}`));
|
|
102
134
|
console.log(chalk.gray(` Metadata: ${metadataPath}`));
|
|
103
135
|
console.log('');
|
package/cli/commands/monitor.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
|
|
4
|
+
const POLL_MS = 5000;
|
|
5
|
+
const MAX_CONSECUTIVE_FAILURES = 5;
|
|
6
|
+
|
|
4
7
|
export async function monitor(options) {
|
|
5
8
|
if (!options.server) {
|
|
6
9
|
console.error(chalk.red('Error: --server URL is required'));
|
|
@@ -12,57 +15,75 @@ export async function monitor(options) {
|
|
|
12
15
|
console.log('');
|
|
13
16
|
|
|
14
17
|
const spinner = ora('Fetching update statistics...').start();
|
|
18
|
+
let intervalId = null;
|
|
19
|
+
let consecutiveFailures = 0;
|
|
20
|
+
let stopping = false;
|
|
21
|
+
|
|
22
|
+
const stop = (code = 0) => {
|
|
23
|
+
if (stopping) return;
|
|
24
|
+
stopping = true;
|
|
25
|
+
if (intervalId) clearInterval(intervalId);
|
|
26
|
+
if (spinner.isSpinning) spinner.stop();
|
|
27
|
+
process.exit(code);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
process.on('SIGINT', () => stop(0));
|
|
31
|
+
process.on('SIGTERM', () => stop(0));
|
|
32
|
+
|
|
33
|
+
const headers = options.key ? { Authorization: `Bearer ${options.key}` } : {};
|
|
34
|
+
|
|
35
|
+
const tick = async () => {
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(`${options.server}/api/stats`, { headers });
|
|
38
|
+
if (!response.ok) throw new Error(`Server returned ${response.status}`);
|
|
39
|
+
|
|
40
|
+
const stats = await response.json();
|
|
41
|
+
consecutiveFailures = 0;
|
|
42
|
+
|
|
43
|
+
spinner.stop();
|
|
44
|
+
console.clear();
|
|
45
|
+
console.log(chalk.blue(`📊 Update Monitor - ${new Date().toLocaleTimeString()}`));
|
|
46
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
47
|
+
console.log('');
|
|
15
48
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
console.log(chalk.blue(`📊 Update Monitor - ${new Date().toLocaleTimeString()}`));
|
|
33
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
34
|
-
console.log('');
|
|
35
|
-
|
|
36
|
-
console.log(chalk.bold('Current Version:'));
|
|
37
|
-
console.log(chalk.gray(` Latest: ${stats.latestVersion || 'N/A'}`));
|
|
38
|
-
console.log(chalk.gray(` Channel: ${stats.channel || 'production'}`));
|
|
39
|
-
console.log('');
|
|
40
|
-
|
|
41
|
-
console.log(chalk.bold('Download Statistics:'));
|
|
42
|
-
console.log(chalk.gray(` Total Downloads: ${stats.totalDownloads || 0}`));
|
|
43
|
-
console.log(chalk.gray(` Downloads Today: ${stats.downloadsToday || 0}`));
|
|
44
|
-
console.log(chalk.gray(` Active Installs: ${stats.activeInstalls || 0}`));
|
|
45
|
-
console.log('');
|
|
46
|
-
|
|
47
|
-
if (stats.recentActivity) {
|
|
48
|
-
console.log(chalk.bold('Recent Activity:'));
|
|
49
|
-
stats.recentActivity.forEach(activity => {
|
|
50
|
-
console.log(chalk.gray(` ${activity.time} - ${activity.action} (${activity.version})`));
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
console.log('');
|
|
55
|
-
console.log(chalk.gray('Press Ctrl+C to stop'));
|
|
56
|
-
|
|
57
|
-
spinner.start('Updating...');
|
|
58
|
-
} catch (error) {
|
|
59
|
-
spinner.fail(`Failed to fetch stats: ${error.message}`);
|
|
60
|
-
spinner.start('Retrying...');
|
|
49
|
+
console.log(chalk.bold('Current Version:'));
|
|
50
|
+
console.log(chalk.gray(` Latest: ${stats.latestVersion || 'N/A'}`));
|
|
51
|
+
console.log(chalk.gray(` Channel: ${stats.channel || 'production'}`));
|
|
52
|
+
console.log('');
|
|
53
|
+
|
|
54
|
+
console.log(chalk.bold('Download Statistics:'));
|
|
55
|
+
console.log(chalk.gray(` Total Downloads: ${stats.totalDownloads || 0}`));
|
|
56
|
+
console.log(chalk.gray(` Downloads Today: ${stats.downloadsToday || 0}`));
|
|
57
|
+
console.log(chalk.gray(` Active Installs: ${stats.activeInstalls || 0}`));
|
|
58
|
+
console.log('');
|
|
59
|
+
|
|
60
|
+
if (stats.recentActivity) {
|
|
61
|
+
console.log(chalk.bold('Recent Activity:'));
|
|
62
|
+
stats.recentActivity.forEach((activity) => {
|
|
63
|
+
console.log(chalk.gray(` ${activity.time} - ${activity.action} (${activity.version})`));
|
|
64
|
+
});
|
|
61
65
|
}
|
|
62
|
-
}, 5000); // Update every 5 seconds
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log(chalk.gray('Press Ctrl+C to stop'));
|
|
69
|
+
|
|
70
|
+
spinner.start('Updating...');
|
|
71
|
+
} catch (error) {
|
|
72
|
+
consecutiveFailures += 1;
|
|
73
|
+
spinner.fail(
|
|
74
|
+
`Failed to fetch stats (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}): ${error.message}`,
|
|
75
|
+
);
|
|
76
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
77
|
+
console.error(
|
|
78
|
+
chalk.red(`\nGiving up after ${MAX_CONSECUTIVE_FAILURES} consecutive failures.`),
|
|
79
|
+
);
|
|
80
|
+
stop(1);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
spinner.start('Retrying...');
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
await tick();
|
|
88
|
+
intervalId = setInterval(tick, POLL_MS);
|
|
89
|
+
}
|
package/cli/index.js
CHANGED
|
@@ -188,29 +188,6 @@ ${chalk.bold('Examples:')}
|
|
|
188
188
|
await createBackend(type, options);
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
-
// Config Commands
|
|
192
|
-
const configCmd = program
|
|
193
|
-
.command('config')
|
|
194
|
-
.description('Configuration commands');
|
|
195
|
-
|
|
196
|
-
configCmd
|
|
197
|
-
.command('check')
|
|
198
|
-
.description('Validate your native-update configuration')
|
|
199
|
-
.action(async () => {
|
|
200
|
-
const { checkConfig } = await import('./commands/config-check.js');
|
|
201
|
-
await checkConfig();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Migration Commands
|
|
205
|
-
program
|
|
206
|
-
.command('migrate')
|
|
207
|
-
.description('Migrate from other OTA solutions')
|
|
208
|
-
.option('--from <solution>', 'Source solution (codepush, appflow)', 'codepush')
|
|
209
|
-
.action(async (options) => {
|
|
210
|
-
const { migrate } = await import('./commands/migrate.js');
|
|
211
|
-
await migrate(options);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
191
|
// Monitoring Commands
|
|
215
192
|
program
|
|
216
193
|
.command('monitor')
|
|
@@ -264,6 +241,15 @@ program.exitOverride();
|
|
|
264
241
|
try {
|
|
265
242
|
await program.parseAsync(process.argv);
|
|
266
243
|
} catch (error) {
|
|
244
|
+
// With exitOverride(), Commander throws for normal help/version output too
|
|
245
|
+
// (exitCode 0). Those are successful displays, not errors — exit quietly.
|
|
246
|
+
if (
|
|
247
|
+
error.code === 'commander.helpDisplayed' ||
|
|
248
|
+
error.code === 'commander.help' ||
|
|
249
|
+
error.code === 'commander.version'
|
|
250
|
+
) {
|
|
251
|
+
process.exit(0);
|
|
252
|
+
}
|
|
267
253
|
if (error.code === 'commander.missingArgument') {
|
|
268
254
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
269
255
|
} else if (error.code === 'commander.unknownCommand') {
|
|
@@ -272,5 +258,5 @@ try {
|
|
|
272
258
|
} else {
|
|
273
259
|
console.error(chalk.red(`Error: ${error.message}`));
|
|
274
260
|
}
|
|
275
|
-
process.exit(1);
|
|
261
|
+
process.exit(error.exitCode ?? 1);
|
|
276
262
|
}
|
package/cli/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "native-update-cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "CLI for Native Update",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=24.16.0"
|
|
8
|
+
},
|
|
6
9
|
"bin": {
|
|
7
10
|
"native-update": "./index.js"
|
|
8
11
|
},
|
|
9
12
|
"dependencies": {
|
|
10
|
-
"
|
|
13
|
+
"archiver": "^8.0.0",
|
|
14
|
+
"chalk": "^5.6.2",
|
|
15
|
+
"commander": "^15.0.0",
|
|
16
|
+
"express": "^5.2.1",
|
|
17
|
+
"ora": "^9.4.0",
|
|
18
|
+
"prompts": "^2.4.2"
|
|
11
19
|
}
|
|
12
|
-
}
|
|
20
|
+
}
|