kasy-cli 1.17.0 → 1.19.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 (110) hide show
  1. package/bin/kasy.js +16 -2
  2. package/lib/commands/add.js +7 -7
  3. package/lib/commands/configure.js +548 -0
  4. package/lib/commands/deploy.js +4 -4
  5. package/lib/commands/doctor.js +17 -0
  6. package/lib/commands/favicon.js +4 -4
  7. package/lib/commands/icon.js +5 -5
  8. package/lib/commands/new.js +483 -324
  9. package/lib/commands/run.js +17 -4
  10. package/lib/commands/splash.js +5 -5
  11. package/lib/commands/update.js +9 -9
  12. package/lib/scaffold/CHANGELOG.json +14 -0
  13. package/lib/scaffold/backends/firebase/enable-auth-via-cli.js +108 -0
  14. package/lib/scaffold/backends/firebase/setup-from-scratch.js +123 -5
  15. package/lib/scaffold/generate.js +24 -8
  16. package/lib/scaffold/shared/post-build.js +8 -0
  17. package/lib/utils/brand.js +16 -12
  18. package/lib/utils/flutter-run.js +139 -11
  19. package/lib/utils/i18n/messages-en.js +62 -5
  20. package/lib/utils/i18n/messages-es.js +62 -5
  21. package/lib/utils/i18n/messages-pt.js +63 -6
  22. package/lib/utils/ui.js +79 -4
  23. package/package.json +1 -2
  24. package/templates/firebase/README.en.md +1 -1
  25. package/templates/firebase/README.es.md +1 -1
  26. package/templates/firebase/README.md +1 -1
  27. package/templates/firebase/android/app/src/main/kotlin/com/aicrus/firebase/kit/MainActivity.kt +0 -15
  28. package/templates/firebase/android/app/src/main/kotlin/com/aicrus/firebase/kit/MyWidget.kt +65 -26
  29. package/templates/firebase/android/app/src/main/res/drawable/widget_add_button.xml +2 -2
  30. package/templates/firebase/android/app/src/main/res/drawable/widget_gradient_bg.xml +7 -2
  31. package/templates/firebase/android/app/src/main/res/drawable/widget_gradient_inner.xml +6 -6
  32. package/templates/firebase/android/app/src/main/res/drawable/widget_plan_pill_bg.xml +1 -1
  33. package/templates/firebase/android/app/src/main/res/drawable/widget_preview_image.xml +2 -2
  34. package/templates/firebase/android/app/src/main/res/drawable/widget_pro_pill_bg.xml +1 -1
  35. package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
  36. package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
  37. package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
  38. package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
  39. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
  40. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
  41. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
  42. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
  43. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
  44. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
  45. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
  46. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
  47. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
  48. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
  49. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
  50. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
  51. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
  52. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
  53. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
  54. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
  55. package/templates/firebase/android/app/src/main/res/layout/widget_preview.xml +3 -3
  56. package/templates/firebase/android/app/src/main/res/values/colors.xml +32 -0
  57. package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
  58. package/templates/firebase/assets/images/splash_logo_dark_android12.png +0 -0
  59. package/templates/firebase/assets/images/splash_logo_light.png +0 -0
  60. package/templates/firebase/assets/images/splash_logo_light_android12.png +0 -0
  61. package/templates/firebase/ios/HomeWidgetExtension/MyWidget.swift +75 -29
  62. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  63. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  64. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  65. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
  66. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
  67. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
  68. package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
  69. package/templates/firebase/lib/components/components.dart +1 -0
  70. package/templates/firebase/lib/components/kasy_avatar.dart +65 -17
  71. package/templates/firebase/lib/components/kasy_avatar_presets.dart +121 -97
  72. package/templates/firebase/lib/components/kasy_button.dart +8 -8
  73. package/templates/firebase/lib/components/kasy_date_picker.dart +2173 -0
  74. package/templates/firebase/lib/components/kasy_tabs.dart +214 -91
  75. package/templates/firebase/lib/components/kasy_text_area.dart +9 -4
  76. package/templates/firebase/lib/components/kasy_text_field.dart +96 -36
  77. package/templates/firebase/lib/components/kasy_text_field_otp.dart +1 -2
  78. package/templates/firebase/lib/core/bottom_menu/bottom_menu.dart +88 -35
  79. package/templates/firebase/lib/core/bottom_menu/bottom_router.dart +7 -43
  80. package/templates/firebase/lib/core/dev_inspector/dev_inspector.dart +118 -16
  81. package/templates/firebase/lib/core/dev_inspector/dev_inspector_service.dart +14 -20
  82. package/templates/firebase/lib/core/home_widgets/home_widget_mywidget_service.dart +12 -18
  83. package/templates/firebase/lib/core/security/secured_storage.dart +56 -15
  84. package/templates/firebase/lib/core/theme/providers/theme_provider.dart +3 -0
  85. package/templates/firebase/lib/core/theme/web_background_sync.dart +3 -0
  86. package/templates/firebase/lib/core/theme/web_background_sync_web.dart +18 -0
  87. package/templates/firebase/lib/core/web_device_preview/web_device_preview.dart +3 -6
  88. package/templates/firebase/lib/features/authentication/api/authentication_api.dart +6 -0
  89. package/templates/firebase/lib/features/home/home_components_page.dart +3 -2
  90. package/templates/firebase/lib/features/home/home_components_preview_registry.dart +949 -77
  91. package/templates/firebase/lib/features/home/home_page.dart +17 -40
  92. package/templates/firebase/lib/features/notifications/ui/notifications_page.dart +1 -16
  93. package/templates/firebase/lib/features/notifications/ui/widgets/empty_notifications.dart +0 -4
  94. package/templates/firebase/lib/features/settings/ui/components/language_switcher.dart +10 -5
  95. package/templates/firebase/lib/i18n/en.i18n.json +2 -1
  96. package/templates/firebase/lib/i18n/es.i18n.json +2 -1
  97. package/templates/firebase/lib/i18n/pt.i18n.json +2 -1
  98. package/templates/firebase/lib/main.dart +34 -34
  99. package/templates/firebase/pubspec.yaml +2 -1
  100. package/templates/firebase/storage.cors.json +8 -0
  101. package/templates/firebase/web/index.html +24 -2
  102. package/templates/firebase/web/splash/img/dark-1x.png +0 -0
  103. package/templates/firebase/web/splash/img/dark-2x.png +0 -0
  104. package/templates/firebase/web/splash/img/dark-3x.png +0 -0
  105. package/templates/firebase/web/splash/img/dark-4x.png +0 -0
  106. package/templates/firebase/web/splash/img/light-1x.png +0 -0
  107. package/templates/firebase/web/splash/img/light-2x.png +0 -0
  108. package/templates/firebase/web/splash/img/light-3x.png +0 -0
  109. package/templates/firebase/web/splash/img/light-4x.png +0 -0
  110. package/templates/firebase/lib/core/bottom_menu/kasy_bart_navigation.dart +0 -22
@@ -17,7 +17,7 @@ const path = require('node:path');
17
17
  const fs = require('fs-extra');
18
18
  const kleur = require('kleur');
19
19
  const ui = require('../utils/ui');
20
- const { printCompactHeader } = require('../utils/brand');
20
+ const { printCompactHeader, paintLime } = require('../utils/brand');
21
21
 
22
22
  const { createTranslator } = require('../utils/i18n');
23
23
  const { getStoredLanguage } = require('../utils/license');
@@ -122,7 +122,7 @@ async function deployFirebase(projectDir, options, tr) {
122
122
  }
123
123
  }
124
124
 
125
- const spinner = ui.timedSpinner();
125
+ const spinner = ui.timedSpinner({ color: paintLime });
126
126
  spinner.start(tr('deploy.firebase.spin'));
127
127
  let steps;
128
128
  try {
@@ -173,7 +173,7 @@ async function deploySupabase(projectDir, tr) {
173
173
  const firebaseProjectId = await readFirebaseProjectId(projectDir);
174
174
 
175
175
  if (firebaseProjectId) {
176
- const fcmSpinner = ui.timedSpinner();
176
+ const fcmSpinner = ui.timedSpinner({ color: paintLime });
177
177
  fcmSpinner.start(tr('deploy.supabase.sakSpin'));
178
178
  const fcmResult = await createFcmServiceAccountKey(firebaseProjectId);
179
179
  fcmSpinner.stop(tr('deploy.supabase.sakSpinDone'));
@@ -194,7 +194,7 @@ async function deploySupabase(projectDir, tr) {
194
194
  }
195
195
 
196
196
  // ── 3. Deploy edge functions ────────────────────────────────────────────
197
- const fnSpinner = ui.timedSpinner();
197
+ const fnSpinner = ui.timedSpinner({ color: paintLime });
198
198
  fnSpinner.start(tr('deploy.supabase.fnSpin'));
199
199
  const fnResult = await deployFunctions(projectDir);
200
200
  fnSpinner.stop(tr('deploy.supabase.fnSpinDone'));
@@ -18,6 +18,7 @@ const {
18
18
  } = require('../utils/apple-release');
19
19
  const { validateCodemagicSetup, codemagicReleaseDocPath } = require('../utils/codemagic-release');
20
20
  const { validateGoogleIosUrlScheme, validateAppleSignInEntitlement, validateFacebookInfoPlist, validateFacebookAndroidStrings, validateRevenueCat } = require('../scaffold/shared/post-build');
21
+ const { listBillingAccounts, checkGcloudAuth } = require('../scaffold/backends/firebase/setup-from-scratch');
21
22
  const { printCompactHeader } = require('../utils/brand');
22
23
 
23
24
  function collectOptionalBackendChecks() {
@@ -248,6 +249,22 @@ async function runDoctor(options = {}) {
248
249
  });
249
250
  }
250
251
 
252
+ // ── Google Cloud billing account (Firebase Blaze) ─────────────────────
253
+ // Only meaningful when gcloud is authenticated; otherwise users already saw
254
+ // a gcloud check fail above and this would just repeat the noise.
255
+ const gcloudAuth = await checkGcloudAuth();
256
+ if (gcloudAuth.ok) {
257
+ ui.log.step(kleur.bold(t('doctor.gcpBilling.title')));
258
+ const billing = await listBillingAccounts();
259
+ if (billing.ok && billing.accounts?.length > 0) {
260
+ const sample = billing.accounts.slice(0, 3).map((a) => `${a.name || a.id} (${a.id})`).join(', ');
261
+ ui.log.success(`${t('doctor.gcpBilling.found', { count: billing.accounts.length })} ${kleur.dim(sample)}`);
262
+ } else {
263
+ ui.log.warn(t('doctor.gcpBilling.missing'));
264
+ ui.log.message(kleur.cyan('https://console.cloud.google.com/billing/create'));
265
+ }
266
+ }
267
+
251
268
  if (hasRequiredFailures(baseResults)) {
252
269
  throw new Error(t('doctor.requiredMissing'));
253
270
  }
@@ -2,7 +2,7 @@ const path = require('node:path');
2
2
  const fs = require('fs-extra');
3
3
  const kleur = require('kleur');
4
4
  const ui = require('../utils/ui');
5
- const { printCompactHeader } = require('../utils/brand');
5
+ const { printCompactHeader, paintLime } = require('../utils/brand');
6
6
  const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
7
7
  const { inspectPng } = require('./splash');
8
8
  const { runFlutterLauncherIcons } = require('./icon');
@@ -50,7 +50,7 @@ async function runFavicon(projectDir, options = {}) {
50
50
  process.exit(1);
51
51
  }
52
52
 
53
- const inspectSpinner = ui.spinner();
53
+ const inspectSpinner = ui.spinner({ color: paintLime });
54
54
  inspectSpinner.start(t('favicon.validating'));
55
55
 
56
56
  let info;
@@ -81,7 +81,7 @@ async function runFavicon(projectDir, options = {}) {
81
81
 
82
82
  const dest = path.join(projectDir, ASSETS_DIR, FAVICON_NAME);
83
83
 
84
- const copySpinner = ui.spinner();
84
+ const copySpinner = ui.spinner({ color: paintLime });
85
85
  copySpinner.start(t('favicon.copying'));
86
86
  await fs.copy(imagePath, dest, { overwrite: true });
87
87
  copySpinner.stop(t('favicon.copied'));
@@ -92,7 +92,7 @@ async function runFavicon(projectDir, options = {}) {
92
92
  return;
93
93
  }
94
94
 
95
- const genSpinner = ui.spinner();
95
+ const genSpinner = ui.spinner({ color: paintLime });
96
96
  genSpinner.start(t('favicon.generating'));
97
97
  const result = await runFlutterLauncherIcons(projectDir);
98
98
  if (result.ok) {
@@ -4,7 +4,7 @@ const { exec } = require('node:child_process');
4
4
  const { promisify } = require('node:util');
5
5
  const kleur = require('kleur');
6
6
  const ui = require('../utils/ui');
7
- const { printCompactHeader } = require('../utils/brand');
7
+ const { printCompactHeader, paintLime } = require('../utils/brand');
8
8
  const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
9
9
  const { inspectPng } = require('./splash');
10
10
  const {
@@ -59,7 +59,7 @@ async function runIcon(projectDir, options = {}) {
59
59
  process.exit(1);
60
60
  }
61
61
 
62
- const inspectSpinner = ui.spinner();
62
+ const inspectSpinner = ui.spinner({ color: paintLime });
63
63
  inspectSpinner.start(t('icon.validating'));
64
64
 
65
65
  let info;
@@ -96,12 +96,12 @@ async function runIcon(projectDir, options = {}) {
96
96
  const androidBgDest = path.join(assetsDir, ANDROID_BG_NAME);
97
97
  const androidFgEmptyDest = path.join(assetsDir, ANDROID_FG_EMPTY_NAME);
98
98
 
99
- const copySpinner = ui.spinner();
99
+ const copySpinner = ui.spinner({ color: paintLime });
100
100
  copySpinner.start(t('icon.copying'));
101
101
  await fs.copy(imagePath, dest, { overwrite: true });
102
102
  copySpinner.stop(t('icon.copied'));
103
103
 
104
- const adaptiveSpinner = ui.spinner();
104
+ const adaptiveSpinner = ui.spinner({ color: paintLime });
105
105
  adaptiveSpinner.start(t('icon.adaptive.generating'));
106
106
  let adaptiveInfo;
107
107
  try {
@@ -126,7 +126,7 @@ async function runIcon(projectDir, options = {}) {
126
126
  return;
127
127
  }
128
128
 
129
- const genSpinner = ui.spinner();
129
+ const genSpinner = ui.spinner({ color: paintLime });
130
130
  genSpinner.start(t('icon.generating'));
131
131
  const result = await runFlutterLauncherIcons(projectDir);
132
132
  if (result.ok) {