kasy-cli 1.5.1 → 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/utils/i18n.js +12 -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/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:',
|
|
@@ -847,6 +851,7 @@ const MESSAGES = {
|
|
|
847
851
|
'new.supabase.q.create.existing': '📂 Usar projeto existente',
|
|
848
852
|
'new.firebase.q.setupMode': 'Como deseja configurar o Firebase?',
|
|
849
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.',
|
|
850
855
|
'new.firebase.q.setupMode.create': '✨ Criar do zero (recomendado para iniciantes)',
|
|
851
856
|
'new.firebase.q.setupMode.existing': '📂 Usar projeto existente',
|
|
852
857
|
'new.firebase.q.region': 'Onde está a maioria dos usuários do seu app?',
|
|
@@ -1225,6 +1230,8 @@ const MESSAGES = {
|
|
|
1225
1230
|
'new.firebase.interactive.billingWaiting': 'Verificando status do Blaze...',
|
|
1226
1231
|
'new.firebase.interactive.billingTimeout': 'Plano Blaze nao confirmado apos o tempo limite. Deploy ignorado — rode manualmente quando estiver pronto.',
|
|
1227
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',
|
|
1228
1235
|
|
|
1229
1236
|
'new.firebase.interactive.ready': 'Pronto para publicar Push Notifications + Regras agora?',
|
|
1230
1237
|
'new.firebase.interactive.deploying': 'Fazendo deploy das Cloud Functions + Regras (Storage e Firestore)...',
|
|
@@ -1263,6 +1270,7 @@ const MESSAGES = {
|
|
|
1263
1270
|
'new.api.success.fcm': '• Firebase e necessario para notificacoes push (FCM) — configure a chave APNs no console do Firebase',
|
|
1264
1271
|
'new.api.success.auth': '• Implemente os endpoints de auth social (Google, Apple) no seu backend',
|
|
1265
1272
|
|
|
1273
|
+
'new.outdated.continueAnyway': 'Continuar criando o projeto com a versao atual?',
|
|
1266
1274
|
'new.success.title': 'Projeto criado com sucesso!',
|
|
1267
1275
|
'new.success.nextSteps': 'Proximos passos:',
|
|
1268
1276
|
'new.success.step.cd': 'Entre na pasta do projeto:',
|
|
@@ -1562,6 +1570,7 @@ const MESSAGES = {
|
|
|
1562
1570
|
'new.supabase.q.create.existing': '📂 Usar proyecto existente',
|
|
1563
1571
|
'new.firebase.q.setupMode': '¿Cómo quieres configurar Firebase?',
|
|
1564
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.',
|
|
1565
1574
|
'new.firebase.q.setupMode.create': '✨ Crear desde cero (recomendado para principiantes)',
|
|
1566
1575
|
'new.firebase.q.setupMode.existing': '📂 Usar proyecto existente',
|
|
1567
1576
|
'new.firebase.q.region': '¿Dónde están la mayoría de los usuarios de tu app?',
|
|
@@ -1940,6 +1949,8 @@ const MESSAGES = {
|
|
|
1940
1949
|
'new.firebase.interactive.billingWaiting': 'Verificando estado del Blaze...',
|
|
1941
1950
|
'new.firebase.interactive.billingTimeout': 'Plan Blaze no confirmado tras el tiempo límite. Despliegue omitido — ejecuta manualmente cuando estés listo.',
|
|
1942
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',
|
|
1943
1954
|
|
|
1944
1955
|
'new.firebase.interactive.ready': '¿Listo para publicar Push Notifications + Reglas ahora?',
|
|
1945
1956
|
'new.firebase.interactive.deploying': 'Desplegando Cloud Functions + Reglas (Storage y Firestore)...',
|
|
@@ -1978,6 +1989,7 @@ const MESSAGES = {
|
|
|
1978
1989
|
'new.api.success.fcm': '• Firebase es necesario para notificaciones push (FCM) — configura la clave APNs en la consola de Firebase',
|
|
1979
1990
|
'new.api.success.auth': '• Implementa los endpoints de auth social (Google, Apple) en tu backend',
|
|
1980
1991
|
|
|
1992
|
+
'new.outdated.continueAnyway': '¿Continuar creando el proyecto con la version actual?',
|
|
1981
1993
|
'new.success.title': '¡Proyecto creado con exito!',
|
|
1982
1994
|
'new.success.nextSteps': 'Proximos pasos:',
|
|
1983
1995
|
'new.success.step.cd': 'Ve a la carpeta del proyecto:',
|
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 };
|