kasy-cli 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/new.js +29 -21
- package/lib/commands/update.js +61 -4
- package/lib/scaffold/catalog.js +49 -0
- package/lib/utils/i18n.js +24 -0
- package/lib/utils/updates.js +40 -1
- package/package.json +1 -1
package/lib/commands/new.js
CHANGED
|
@@ -73,6 +73,7 @@ const fs = require('fs-extra');
|
|
|
73
73
|
const { createTranslator } = require('../utils/i18n');
|
|
74
74
|
const { getStoredLanguage, setStoredLanguage } = require('../utils/license');
|
|
75
75
|
const { promptLanguage } = require('../utils/prompts');
|
|
76
|
+
const { warnIfOutdatedBeforeNew } = require('../utils/updates');
|
|
76
77
|
const {
|
|
77
78
|
getBaseChecks,
|
|
78
79
|
getPlatformChecks,
|
|
@@ -517,6 +518,11 @@ async function runNew(directory, { language: langHint = null, backend: backendHi
|
|
|
517
518
|
const tr = createTranslator(language);
|
|
518
519
|
const cancel = () => onCancel(tr);
|
|
519
520
|
|
|
521
|
+
// ── 1b. Version check — warn if outdated, let user decide ───────────────
|
|
522
|
+
if (!yes) {
|
|
523
|
+
await warnIfOutdatedBeforeNew(tr);
|
|
524
|
+
}
|
|
525
|
+
|
|
520
526
|
// ── 2. Environment checks (non-blocking — only warnings) ────────────────
|
|
521
527
|
const envChecks = [...getBaseChecks(), ...getPlatformChecks()];
|
|
522
528
|
await runChecks(envChecks, tr('new.checks.environment'), {
|
|
@@ -595,26 +601,7 @@ async function runNew(directory, { language: langHint = null, backend: backendHi
|
|
|
595
601
|
}
|
|
596
602
|
}
|
|
597
603
|
|
|
598
|
-
// ──
|
|
599
|
-
let isQuick = yes; // --yes implies Quick mode
|
|
600
|
-
if (!yes) {
|
|
601
|
-
const { wizardMode } = await prompts(
|
|
602
|
-
{
|
|
603
|
-
type: 'select',
|
|
604
|
-
name: 'wizardMode',
|
|
605
|
-
message: tr('new.q.mode'),
|
|
606
|
-
choices: [
|
|
607
|
-
{ title: tr('new.q.mode.quick'), value: 'quick' },
|
|
608
|
-
{ title: tr('new.q.mode.advanced'), value: 'advanced' },
|
|
609
|
-
],
|
|
610
|
-
initial: 0,
|
|
611
|
-
},
|
|
612
|
-
{ onCancel: cancel }
|
|
613
|
-
);
|
|
614
|
-
isQuick = wizardMode === 'quick';
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
// ── 4b. Firebase setup mode (create vs existing) — ask first so prereqs are correct ─
|
|
604
|
+
// ── Firebase setup mode (create vs existing) ────────────────────────────────
|
|
618
605
|
// Firebase backend: full setup. Supabase/API: Firebase only for push notifications (FCM).
|
|
619
606
|
let firebaseSetupMode = 'existing';
|
|
620
607
|
if (!yes) {
|
|
@@ -634,6 +621,7 @@ async function runNew(directory, { language: langHint = null, backend: backendHi
|
|
|
634
621
|
);
|
|
635
622
|
firebaseSetupMode = setupMode;
|
|
636
623
|
} else if (backend === 'supabase' || backend === 'api') {
|
|
624
|
+
console.log(kleur.dim(`\n ℹ ${tr('new.firebase.q.setupMode.push.explain')}\n`));
|
|
637
625
|
const { setupMode } = await prompts(
|
|
638
626
|
{
|
|
639
627
|
type: 'select',
|
|
@@ -651,7 +639,27 @@ async function runNew(directory, { language: langHint = null, backend: backendHi
|
|
|
651
639
|
}
|
|
652
640
|
}
|
|
653
641
|
|
|
654
|
-
// ──
|
|
642
|
+
// ── Wizard mode — Quick (few questions) or Full (all options) ───────────────
|
|
643
|
+
// Asked after app name + setup context are clear, so the user understands what it controls.
|
|
644
|
+
let isQuick = yes; // --yes implies Quick mode
|
|
645
|
+
if (!yes) {
|
|
646
|
+
const { wizardMode } = await prompts(
|
|
647
|
+
{
|
|
648
|
+
type: 'select',
|
|
649
|
+
name: 'wizardMode',
|
|
650
|
+
message: tr('new.q.mode'),
|
|
651
|
+
choices: [
|
|
652
|
+
{ title: tr('new.q.mode.quick'), value: 'quick' },
|
|
653
|
+
{ title: tr('new.q.mode.advanced'), value: 'advanced' },
|
|
654
|
+
],
|
|
655
|
+
initial: 0,
|
|
656
|
+
},
|
|
657
|
+
{ onCancel: cancel }
|
|
658
|
+
);
|
|
659
|
+
isQuick = wizardMode === 'quick';
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
// ── Backend-specific prerequisites (dynamic: only show what's not yet verified) ─
|
|
655
663
|
printPrerequisites(tr, backend, firebaseSetupMode, backendCheckResults);
|
|
656
664
|
|
|
657
665
|
// ── Firebase region — Quick mode uses default (us-central1) ──────────
|
package/lib/commands/update.js
CHANGED
|
@@ -12,6 +12,7 @@ const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
|
|
|
12
12
|
const {
|
|
13
13
|
AVAILABLE_FEATURES,
|
|
14
14
|
BASE_COMPONENT_FILES,
|
|
15
|
+
CORE_FILES,
|
|
15
16
|
CORE_SOURCE_DIR,
|
|
16
17
|
FEATURES_PATCH_DIR,
|
|
17
18
|
normalizeFeature,
|
|
@@ -29,6 +30,7 @@ const NEEDS_BUILD_RUNNER = [
|
|
|
29
30
|
'revenuecat', 'analytics', 'sentry', 'onboarding', 'llm_chat', 'feedback',
|
|
30
31
|
];
|
|
31
32
|
const COMPONENTS_UPDATE_TARGET = 'components';
|
|
33
|
+
const CORE_UPDATE_TARGET = 'core';
|
|
32
34
|
const IOS_RELEASE_UPDATE_TARGET = 'ios-release';
|
|
33
35
|
|
|
34
36
|
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
@@ -80,6 +82,10 @@ function normalizeUpdateTarget(value) {
|
|
|
80
82
|
if (componentAliases.has(normalized)) {
|
|
81
83
|
return COMPONENTS_UPDATE_TARGET;
|
|
82
84
|
}
|
|
85
|
+
const coreAliases = new Set(['core', 'core_files', 'corefiles']);
|
|
86
|
+
if (coreAliases.has(normalized)) {
|
|
87
|
+
return CORE_UPDATE_TARGET;
|
|
88
|
+
}
|
|
83
89
|
const iosAliases = new Set(['ios_release', 'iosrelease']);
|
|
84
90
|
if (iosAliases.has(normalized) || normalized === 'ios-release') {
|
|
85
91
|
return IOS_RELEASE_UPDATE_TARGET;
|
|
@@ -87,9 +93,9 @@ function normalizeUpdateTarget(value) {
|
|
|
87
93
|
return null;
|
|
88
94
|
}
|
|
89
95
|
|
|
90
|
-
async function
|
|
96
|
+
async function applyFileList(fileList, projectDir) {
|
|
91
97
|
let filesApplied = 0;
|
|
92
|
-
for (const relativePath of
|
|
98
|
+
for (const relativePath of fileList) {
|
|
93
99
|
const sourcePath = path.join(CORE_SOURCE_DIR, relativePath);
|
|
94
100
|
if (!(await fs.pathExists(sourcePath))) {
|
|
95
101
|
continue;
|
|
@@ -102,6 +108,14 @@ async function applyBaseComponents(projectDir) {
|
|
|
102
108
|
return filesApplied;
|
|
103
109
|
}
|
|
104
110
|
|
|
111
|
+
function applyBaseComponents(projectDir) {
|
|
112
|
+
return applyFileList(BASE_COMPONENT_FILES, projectDir);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function applyCoreFiles(projectDir) {
|
|
116
|
+
return applyFileList(CORE_FILES, projectDir);
|
|
117
|
+
}
|
|
118
|
+
|
|
105
119
|
/** Same detection logic used by add.js and remove.js. */
|
|
106
120
|
async function getActiveModules(kitSetup, projectDir) {
|
|
107
121
|
const modules = [];
|
|
@@ -203,6 +217,49 @@ async function runUpdate(module, options = {}) {
|
|
|
203
217
|
return;
|
|
204
218
|
}
|
|
205
219
|
|
|
220
|
+
if (normalizedTarget === CORE_UPDATE_TARGET) {
|
|
221
|
+
if (!options.yes) {
|
|
222
|
+
console.log(kleur.yellow(`\n ⚠ ${t('update.warn.commitComponents')}\n`));
|
|
223
|
+
const { confirmed } = await prompts(
|
|
224
|
+
{ type: 'confirm', name: 'confirmed', message: t('update.confirmCore'), initial: false },
|
|
225
|
+
{ onCancel: () => { throw new Error(t('update.cancelled')); } }
|
|
226
|
+
);
|
|
227
|
+
if (!confirmed) {
|
|
228
|
+
console.log(kleur.dim(`\n${t('update.cancelled')}\n`));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.log('');
|
|
234
|
+
const spinner = ora(t('update.applyingCore')).start();
|
|
235
|
+
try {
|
|
236
|
+
const filesApplied = await applyCoreFiles(projectDir);
|
|
237
|
+
if (filesApplied === 0) {
|
|
238
|
+
spinner.warn(t('update.noComponentFiles'));
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
spinner.succeed(t('update.appliedCore', { count: filesApplied }));
|
|
242
|
+
} catch (err) {
|
|
243
|
+
spinner.fail(t('update.applyComponentsFailed'));
|
|
244
|
+
throw err;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
{
|
|
248
|
+
const spinnerPubGet = ora(t('update.pubGet')).start();
|
|
249
|
+
try {
|
|
250
|
+
await execAsync('flutter pub get', { cwd: projectDir, timeout: 300_000 });
|
|
251
|
+
spinnerPubGet.succeed(t('update.pubGetDone'));
|
|
252
|
+
} catch {
|
|
253
|
+
spinnerPubGet.warn(t('update.pubGetFailed'));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
kitSetup.cliVersion = currentVersion;
|
|
258
|
+
await fs.outputFile(kitSetupPath, JSON.stringify(kitSetup, null, 2) + '\n', 'utf8');
|
|
259
|
+
console.log(kleur.green(`\n✓ ${t('update.coreSuccess')}\n`));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
206
263
|
if (normalizedTarget === IOS_RELEASE_UPDATE_TARGET) {
|
|
207
264
|
const patchDir = path.join(FEATURES_PATCH_DIR, 'ios-release');
|
|
208
265
|
if (!(await fs.pathExists(patchDir))) {
|
|
@@ -249,7 +306,7 @@ async function runUpdate(module, options = {}) {
|
|
|
249
306
|
throw new Error(
|
|
250
307
|
t('update.error.unknownTarget', {
|
|
251
308
|
module,
|
|
252
|
-
list: [...AVAILABLE_FEATURES, COMPONENTS_UPDATE_TARGET, IOS_RELEASE_UPDATE_TARGET].join(', '),
|
|
309
|
+
list: [...AVAILABLE_FEATURES, COMPONENTS_UPDATE_TARGET, CORE_UPDATE_TARGET, IOS_RELEASE_UPDATE_TARGET].join(', '),
|
|
253
310
|
})
|
|
254
311
|
);
|
|
255
312
|
}
|
|
@@ -335,7 +392,7 @@ async function runUpdate(module, options = {}) {
|
|
|
335
392
|
|
|
336
393
|
// ── Mode B: show status ──────────────────────────────────────────────────────
|
|
337
394
|
const alreadyUpToDate = projectVersion && !isNewer(currentVersion, projectVersion);
|
|
338
|
-
const modulesForChangelog = [...new Set([...activeModules, COMPONENTS_UPDATE_TARGET])];
|
|
395
|
+
const modulesForChangelog = [...new Set([...activeModules, COMPONENTS_UPDATE_TARGET, CORE_UPDATE_TARGET])];
|
|
339
396
|
const changes = getChangesSince(changelog, projectVersion, modulesForChangelog, options.language);
|
|
340
397
|
|
|
341
398
|
// Modules in this project that have patch dirs (can be re-applied)
|
package/lib/scaffold/catalog.js
CHANGED
|
@@ -74,6 +74,54 @@ const DEFAULT_FEATURES = [...AVAILABLE_FEATURES];
|
|
|
74
74
|
* shared widgets); keep this list in sync with `Firebase/lib/components/` and
|
|
75
75
|
* the home component catalog.
|
|
76
76
|
*/
|
|
77
|
+
const CORE_FILES = [
|
|
78
|
+
// Dev tools
|
|
79
|
+
'lib/core/web_device_preview/web_device_preview.dart',
|
|
80
|
+
'lib/core/dev_inspector/dev_inspector.dart',
|
|
81
|
+
'lib/core/dev_inspector/dev_inspector_highlight.dart',
|
|
82
|
+
'lib/core/dev_inspector/dev_inspector_info.dart',
|
|
83
|
+
'lib/core/dev_inspector/dev_inspector_panel.dart',
|
|
84
|
+
'lib/core/dev_inspector/dev_inspector_service.dart',
|
|
85
|
+
'lib/core/keyboard_fix/keyboard_flicker_fix.dart',
|
|
86
|
+
// Animations
|
|
87
|
+
'lib/core/animations/bottomfade_anim.dart',
|
|
88
|
+
'lib/core/animations/movefade_anim.dart',
|
|
89
|
+
'lib/core/animations/slideright_anim.dart',
|
|
90
|
+
// Core widgets (pure utilities, never user-modified)
|
|
91
|
+
'lib/core/widgets/debouncer.dart',
|
|
92
|
+
'lib/core/widgets/kasy_hover.dart',
|
|
93
|
+
'lib/core/widgets/kasy_pressable.dart',
|
|
94
|
+
'lib/core/widgets/kasy_scroll_behavior.dart',
|
|
95
|
+
'lib/core/widgets/keyboard_visibility.dart',
|
|
96
|
+
'lib/core/widgets/page_background.dart',
|
|
97
|
+
'lib/core/widgets/page_not_found.dart',
|
|
98
|
+
'lib/core/widgets/responsive_layout.dart',
|
|
99
|
+
'lib/core/widgets/update_bottom_sheet.dart',
|
|
100
|
+
// Page transitions (pure utilities)
|
|
101
|
+
'lib/core/navigation/kasy_fade_page_transitions_builder.dart',
|
|
102
|
+
'lib/core/navigation/kasy_material_page_route.dart',
|
|
103
|
+
'lib/core/navigation/kasy_page_transition.dart',
|
|
104
|
+
'lib/core/navigation/kasy_route_transition.dart',
|
|
105
|
+
'lib/core/navigation/kasy_transition_kind.dart',
|
|
106
|
+
// Utilities
|
|
107
|
+
'lib/core/toast/toast_service.dart',
|
|
108
|
+
'lib/core/ui/app_dialog.dart',
|
|
109
|
+
'lib/core/icons/kasy_icons.dart',
|
|
110
|
+
'lib/core/haptics/kasy_haptics.dart',
|
|
111
|
+
'lib/core/haptics/haptic_feedback_notifier.dart',
|
|
112
|
+
// Theme (colors.dart and shadows.dart are in BASE_COMPONENT_FILES)
|
|
113
|
+
'lib/core/theme/spacing.dart',
|
|
114
|
+
'lib/core/theme/texts.dart',
|
|
115
|
+
'lib/core/theme/radius.dart',
|
|
116
|
+
'lib/core/theme/theme.dart',
|
|
117
|
+
'lib/core/theme/theme_data/theme_data.dart',
|
|
118
|
+
'lib/core/theme/theme_data/theme_data_factory.dart',
|
|
119
|
+
'lib/core/theme/extensions/theme_extension.dart',
|
|
120
|
+
'lib/core/theme/providers/kasy_theme.dart',
|
|
121
|
+
'lib/core/theme/providers/theme_provider.dart',
|
|
122
|
+
'lib/core/theme/universal_theme.dart',
|
|
123
|
+
];
|
|
124
|
+
|
|
77
125
|
const BASE_COMPONENT_FILES = [
|
|
78
126
|
'lib/core/theme/colors.dart',
|
|
79
127
|
'lib/core/theme/shadows.dart',
|
|
@@ -170,6 +218,7 @@ module.exports = {
|
|
|
170
218
|
AVAILABLE_FEATURES,
|
|
171
219
|
DEFAULT_FEATURES,
|
|
172
220
|
BASE_COMPONENT_FILES,
|
|
221
|
+
CORE_FILES,
|
|
173
222
|
normalizeBackend,
|
|
174
223
|
normalizeFeature,
|
|
175
224
|
parseFeatureList,
|
package/lib/utils/i18n.js
CHANGED
|
@@ -132,6 +132,7 @@ const MESSAGES = {
|
|
|
132
132
|
'new.supabase.q.create.existing': '📂 Use existing project',
|
|
133
133
|
'new.firebase.q.setupMode': 'How do you want to set up Firebase?',
|
|
134
134
|
'new.firebase.q.setupMode.push': 'Firebase project for push notifications (FCM):',
|
|
135
|
+
'new.firebase.q.setupMode.push.explain': 'Push notifications (FCM) require a Firebase project, even when your main backend is Supabase or API REST.',
|
|
135
136
|
'new.firebase.q.setupMode.create': '✨ Create from scratch (recommended for beginners)',
|
|
136
137
|
'new.firebase.q.setupMode.existing': '📂 Use existing project',
|
|
137
138
|
'new.firebase.q.region': 'Where are most of your app users located?',
|
|
@@ -510,6 +511,8 @@ const MESSAGES = {
|
|
|
510
511
|
'new.firebase.interactive.billingWaiting': 'Checking Blaze status...',
|
|
511
512
|
'new.firebase.interactive.billingTimeout': 'Blaze plan not confirmed after timeout. Deploy skipped — run manually when ready.',
|
|
512
513
|
'new.firebase.interactive.authWarn': 'Could not enable Email/Password and Anonymous auth automatically. Enable manually:',
|
|
514
|
+
'new.firebase.existing.apisFailed': 'Could not activate APIs:',
|
|
515
|
+
'new.firebase.existing.googleSignInManual': 'Google Sign-In: enable manually in Authentication → Sign-in method → Google',
|
|
513
516
|
|
|
514
517
|
'new.firebase.interactive.ready': 'Ready to deploy Push Notifications + Security Rules now?',
|
|
515
518
|
'new.firebase.interactive.deploying': 'Deploying Cloud Functions + Firestore/Storage rules...',
|
|
@@ -548,6 +551,7 @@ const MESSAGES = {
|
|
|
548
551
|
'new.api.success.fcm': '• Firebase is required for push notifications (FCM) — configure APNs key in Firebase console',
|
|
549
552
|
'new.api.success.auth': '• Implement the social auth endpoints (Google, Apple) on your backend',
|
|
550
553
|
|
|
554
|
+
'new.outdated.continueAnyway': 'Continue creating the project with the current version?',
|
|
551
555
|
'new.success.title': 'Project created successfully!',
|
|
552
556
|
'new.success.nextSteps': 'Next steps:',
|
|
553
557
|
'new.success.step.cd': 'Go to your project folder:',
|
|
@@ -698,11 +702,14 @@ const MESSAGES = {
|
|
|
698
702
|
'update.warn.commitComponents': 'This will overwrite base component files. Make sure you have committed your changes first.',
|
|
699
703
|
'update.confirm': 'Overwrite feature "{module}" files with the latest version?',
|
|
700
704
|
'update.confirmComponents': 'Overwrite base component files with the latest version?',
|
|
705
|
+
'update.confirmCore': 'Overwrite core files (animations, widgets, theme, dev tools) with the latest version?',
|
|
701
706
|
'update.cancelled': 'Cancelled.',
|
|
702
707
|
'update.applying': 'Applying update for feature: {module}',
|
|
703
708
|
'update.applyingComponents': 'Applying update for base components...',
|
|
709
|
+
'update.applyingCore': 'Applying update for core files...',
|
|
704
710
|
'update.applied': 'Feature {module} updated',
|
|
705
711
|
'update.appliedComponents': '{count} base component files updated',
|
|
712
|
+
'update.appliedCore': '{count} core files updated',
|
|
706
713
|
'update.applyFailed': 'Failed to apply update for feature {module}',
|
|
707
714
|
'update.applyComponentsFailed': 'Failed to apply update for base components',
|
|
708
715
|
'update.noPatch': 'Feature "{module}" has no files to update (configuration-only feature).',
|
|
@@ -715,6 +722,7 @@ const MESSAGES = {
|
|
|
715
722
|
'update.buildRunnerFailed': 'build_runner failed — run it manually',
|
|
716
723
|
'update.success': 'Feature "{module}" updated successfully.',
|
|
717
724
|
'update.componentsSuccess': 'Base components updated successfully.',
|
|
725
|
+
'update.coreSuccess': 'Core files updated successfully.',
|
|
718
726
|
},
|
|
719
727
|
pt: {
|
|
720
728
|
'cli.tagline': 'Crie apps móveis sem dor de configuração',
|
|
@@ -843,6 +851,7 @@ const MESSAGES = {
|
|
|
843
851
|
'new.supabase.q.create.existing': '📂 Usar projeto existente',
|
|
844
852
|
'new.firebase.q.setupMode': 'Como deseja configurar o Firebase?',
|
|
845
853
|
'new.firebase.q.setupMode.push': 'Projeto Firebase para notificações push (FCM):',
|
|
854
|
+
'new.firebase.q.setupMode.push.explain': 'Notificações push (FCM) precisam de um projeto Firebase, mesmo quando seu backend principal é Supabase ou API REST.',
|
|
846
855
|
'new.firebase.q.setupMode.create': '✨ Criar do zero (recomendado para iniciantes)',
|
|
847
856
|
'new.firebase.q.setupMode.existing': '📂 Usar projeto existente',
|
|
848
857
|
'new.firebase.q.region': 'Onde está a maioria dos usuários do seu app?',
|
|
@@ -1221,6 +1230,8 @@ const MESSAGES = {
|
|
|
1221
1230
|
'new.firebase.interactive.billingWaiting': 'Verificando status do Blaze...',
|
|
1222
1231
|
'new.firebase.interactive.billingTimeout': 'Plano Blaze nao confirmado apos o tempo limite. Deploy ignorado — rode manualmente quando estiver pronto.',
|
|
1223
1232
|
'new.firebase.interactive.authWarn': 'Nao foi possivel ativar Email/Senha e Anonimo automaticamente. Ative manualmente:',
|
|
1233
|
+
'new.firebase.existing.apisFailed': 'Nao foi possivel ativar APIs:',
|
|
1234
|
+
'new.firebase.existing.googleSignInManual': 'Google Sign-In: ative manualmente em Authentication → Sign-in method → Google',
|
|
1224
1235
|
|
|
1225
1236
|
'new.firebase.interactive.ready': 'Pronto para publicar Push Notifications + Regras agora?',
|
|
1226
1237
|
'new.firebase.interactive.deploying': 'Fazendo deploy das Cloud Functions + Regras (Storage e Firestore)...',
|
|
@@ -1259,6 +1270,7 @@ const MESSAGES = {
|
|
|
1259
1270
|
'new.api.success.fcm': '• Firebase e necessario para notificacoes push (FCM) — configure a chave APNs no console do Firebase',
|
|
1260
1271
|
'new.api.success.auth': '• Implemente os endpoints de auth social (Google, Apple) no seu backend',
|
|
1261
1272
|
|
|
1273
|
+
'new.outdated.continueAnyway': 'Continuar criando o projeto com a versao atual?',
|
|
1262
1274
|
'new.success.title': 'Projeto criado com sucesso!',
|
|
1263
1275
|
'new.success.nextSteps': 'Proximos passos:',
|
|
1264
1276
|
'new.success.step.cd': 'Entre na pasta do projeto:',
|
|
@@ -1409,11 +1421,14 @@ const MESSAGES = {
|
|
|
1409
1421
|
'update.warn.commitComponents': 'Isso vai sobrescrever arquivos dos componentes base. Faca commit de tudo antes de continuar.',
|
|
1410
1422
|
'update.confirm': 'Sobrescrever arquivos da feature "{module}" com a versao mais recente?',
|
|
1411
1423
|
'update.confirmComponents': 'Sobrescrever arquivos dos componentes base com a versao mais recente?',
|
|
1424
|
+
'update.confirmCore': 'Sobrescrever arquivos do core (animacoes, widgets, tema, ferramentas de dev) com a versao mais recente?',
|
|
1412
1425
|
'update.cancelled': 'Cancelado.',
|
|
1413
1426
|
'update.applying': 'Aplicando atualizacao da feature: {module}',
|
|
1414
1427
|
'update.applyingComponents': 'Aplicando atualizacao dos componentes base...',
|
|
1428
|
+
'update.applyingCore': 'Aplicando atualizacao dos arquivos de core...',
|
|
1415
1429
|
'update.applied': 'Feature {module} atualizada',
|
|
1416
1430
|
'update.appliedComponents': '{count} arquivos de componentes base atualizados',
|
|
1431
|
+
'update.appliedCore': '{count} arquivos de core atualizados',
|
|
1417
1432
|
'update.applyFailed': 'Falha ao aplicar atualizacao da feature {module}',
|
|
1418
1433
|
'update.applyComponentsFailed': 'Falha ao aplicar atualizacao dos componentes base',
|
|
1419
1434
|
'update.noPatch': 'Feature "{module}" nao tem arquivos para atualizar (feature so de configuracao).',
|
|
@@ -1426,6 +1441,7 @@ const MESSAGES = {
|
|
|
1426
1441
|
'update.buildRunnerFailed': 'build_runner falhou — execute manualmente',
|
|
1427
1442
|
'update.success': 'Feature "{module}" atualizada com sucesso.',
|
|
1428
1443
|
'update.componentsSuccess': 'Componentes base atualizados com sucesso.',
|
|
1444
|
+
'update.coreSuccess': 'Arquivos de core atualizados com sucesso.',
|
|
1429
1445
|
},
|
|
1430
1446
|
es: {
|
|
1431
1447
|
'cli.tagline': 'Crea apps móviles sin dolor de configuración',
|
|
@@ -1554,6 +1570,7 @@ const MESSAGES = {
|
|
|
1554
1570
|
'new.supabase.q.create.existing': '📂 Usar proyecto existente',
|
|
1555
1571
|
'new.firebase.q.setupMode': '¿Cómo quieres configurar Firebase?',
|
|
1556
1572
|
'new.firebase.q.setupMode.push': 'Proyecto Firebase para notificaciones push (FCM):',
|
|
1573
|
+
'new.firebase.q.setupMode.push.explain': 'Las notificaciones push (FCM) requieren un proyecto Firebase, incluso cuando tu backend principal es Supabase o API REST.',
|
|
1557
1574
|
'new.firebase.q.setupMode.create': '✨ Crear desde cero (recomendado para principiantes)',
|
|
1558
1575
|
'new.firebase.q.setupMode.existing': '📂 Usar proyecto existente',
|
|
1559
1576
|
'new.firebase.q.region': '¿Dónde están la mayoría de los usuarios de tu app?',
|
|
@@ -1932,6 +1949,8 @@ const MESSAGES = {
|
|
|
1932
1949
|
'new.firebase.interactive.billingWaiting': 'Verificando estado del Blaze...',
|
|
1933
1950
|
'new.firebase.interactive.billingTimeout': 'Plan Blaze no confirmado tras el tiempo límite. Despliegue omitido — ejecuta manualmente cuando estés listo.',
|
|
1934
1951
|
'new.firebase.interactive.authWarn': 'No se pudo activar Email/Contraseña y Anónimo automáticamente. Actívalos manualmente:',
|
|
1952
|
+
'new.firebase.existing.apisFailed': 'No se pudieron activar las APIs:',
|
|
1953
|
+
'new.firebase.existing.googleSignInManual': 'Google Sign-In: activa manualmente en Authentication → Sign-in method → Google',
|
|
1935
1954
|
|
|
1936
1955
|
'new.firebase.interactive.ready': '¿Listo para publicar Push Notifications + Reglas ahora?',
|
|
1937
1956
|
'new.firebase.interactive.deploying': 'Desplegando Cloud Functions + Reglas (Storage y Firestore)...',
|
|
@@ -1970,6 +1989,7 @@ const MESSAGES = {
|
|
|
1970
1989
|
'new.api.success.fcm': '• Firebase es necesario para notificaciones push (FCM) — configura la clave APNs en la consola de Firebase',
|
|
1971
1990
|
'new.api.success.auth': '• Implementa los endpoints de auth social (Google, Apple) en tu backend',
|
|
1972
1991
|
|
|
1992
|
+
'new.outdated.continueAnyway': '¿Continuar creando el proyecto con la version actual?',
|
|
1973
1993
|
'new.success.title': '¡Proyecto creado con exito!',
|
|
1974
1994
|
'new.success.nextSteps': 'Proximos pasos:',
|
|
1975
1995
|
'new.success.step.cd': 'Ve a la carpeta del proyecto:',
|
|
@@ -2120,11 +2140,14 @@ const MESSAGES = {
|
|
|
2120
2140
|
'update.warn.commitComponents': 'Esto sobreescribira archivos de los componentes base. Asegurate de haber hecho commit antes.',
|
|
2121
2141
|
'update.confirm': 'Sobreescribir archivos de la feature "{module}" con la version mas reciente?',
|
|
2122
2142
|
'update.confirmComponents': 'Sobreescribir archivos de los componentes base con la version mas reciente?',
|
|
2143
|
+
'update.confirmCore': 'Sobreescribir archivos de core (animaciones, widgets, tema, herramientas dev) con la version mas reciente?',
|
|
2123
2144
|
'update.cancelled': 'Cancelado.',
|
|
2124
2145
|
'update.applying': 'Aplicando actualizacion de la feature: {module}',
|
|
2125
2146
|
'update.applyingComponents': 'Aplicando actualizacion de componentes base...',
|
|
2147
|
+
'update.applyingCore': 'Aplicando actualizacion de archivos de core...',
|
|
2126
2148
|
'update.applied': 'Feature {module} actualizada',
|
|
2127
2149
|
'update.appliedComponents': '{count} archivos de componentes base actualizados',
|
|
2150
|
+
'update.appliedCore': '{count} archivos de core actualizados',
|
|
2128
2151
|
'update.applyFailed': 'Error al aplicar actualizacion de la feature {module}',
|
|
2129
2152
|
'update.applyComponentsFailed': 'Error al aplicar actualizacion de componentes base',
|
|
2130
2153
|
'update.noPatch': 'La feature "{module}" no tiene archivos para actualizar (feature solo de configuracion).',
|
|
@@ -2137,6 +2160,7 @@ const MESSAGES = {
|
|
|
2137
2160
|
'update.buildRunnerFailed': 'build_runner fallo — ejecutalo manualmente',
|
|
2138
2161
|
'update.success': 'Feature "{module}" actualizada exitosamente.',
|
|
2139
2162
|
'update.componentsSuccess': 'Componentes base actualizados exitosamente.',
|
|
2163
|
+
'update.coreSuccess': 'Archivos de core actualizados exitosamente.',
|
|
2140
2164
|
}
|
|
2141
2165
|
};
|
|
2142
2166
|
|
package/lib/utils/updates.js
CHANGED
|
@@ -4,6 +4,7 @@ const https = require('node:https');
|
|
|
4
4
|
const path = require('node:path');
|
|
5
5
|
const { existsSync, readJsonSync, writeJsonSync, ensureDirSync } = require('fs-extra');
|
|
6
6
|
const kleur = require('kleur');
|
|
7
|
+
const prompts = require('prompts');
|
|
7
8
|
const pkg = require('../../package.json');
|
|
8
9
|
const { CONFIG_PATH } = require('./license');
|
|
9
10
|
|
|
@@ -94,4 +95,42 @@ async function checkForUpdates() {
|
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Chamado antes de kasy new. Se houver versão mais nova no cache,
|
|
100
|
+
* mostra aviso e pergunta se quer continuar ou sair para atualizar.
|
|
101
|
+
* Nunca bloqueia — se o usuário ignorar, o fluxo segue normalmente.
|
|
102
|
+
*/
|
|
103
|
+
async function warnIfOutdatedBeforeNew(t) {
|
|
104
|
+
try {
|
|
105
|
+
const cache = (readConfig().updateCheck) || {};
|
|
106
|
+
if (!cache.latestVersion || !isNewer(cache.latestVersion, pkg.version)) return;
|
|
107
|
+
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log(
|
|
110
|
+
kleur.bgYellow().black(' VERSÃO DESATUALIZADA ') + ' ' +
|
|
111
|
+
kleur.bold(`v${cache.latestVersion} disponível`) +
|
|
112
|
+
kleur.dim(` (você tem v${pkg.version})`)
|
|
113
|
+
);
|
|
114
|
+
console.log(kleur.dim(' Projetos novos são criados com a versão que você tem instalada.'));
|
|
115
|
+
console.log(kleur.dim(' Para criar com a versão mais recente: ') + kleur.cyan('kasy upgrade') + kleur.dim(' (requer assinatura ativa)'));
|
|
116
|
+
console.log('');
|
|
117
|
+
|
|
118
|
+
const { proceed } = await prompts({
|
|
119
|
+
type: 'confirm',
|
|
120
|
+
name: 'proceed',
|
|
121
|
+
message: t ? t('new.outdated.continueAnyway') : 'Continuar com a versão atual?',
|
|
122
|
+
initial: true,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (proceed === false) {
|
|
126
|
+
console.log('');
|
|
127
|
+
console.log(kleur.cyan(' kasy upgrade'));
|
|
128
|
+
console.log('');
|
|
129
|
+
process.exit(0);
|
|
130
|
+
}
|
|
131
|
+
} catch {
|
|
132
|
+
// Nunca travar o kasy new por causa do aviso de versão
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = { checkForUpdates, warnIfOutdatedBeforeNew };
|