kasy-cli 1.5.3 → 1.7.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/bin/kasy.js +7 -4
- package/docs/cli-reference.md +4 -6
- package/lib/commands/add.js +128 -102
- package/lib/commands/check.js +55 -38
- package/lib/commands/codemagic.js +61 -58
- package/lib/commands/deploy.js +49 -45
- package/lib/commands/docs.js +19 -18
- package/lib/commands/doctor.js +46 -44
- package/lib/commands/features.js +42 -20
- package/lib/commands/ios.js +69 -69
- package/lib/commands/new.js +529 -771
- package/lib/commands/notifications.js +59 -59
- package/lib/commands/remove.js +28 -27
- package/lib/commands/run.js +3 -1
- package/lib/commands/update.js +104 -96
- package/lib/commands/validate.js +24 -19
- package/lib/scaffold/catalog.js +45 -11
- package/lib/scaffold/features/README.md +1 -2
- package/lib/scaffold/shared/generator-utils.js +1 -1
- package/lib/utils/apple-release.js +23 -11
- package/lib/utils/brand.js +72 -0
- package/lib/utils/checks.js +20 -9
- package/lib/utils/i18n.js +102 -78
- package/lib/utils/prompts.js +29 -177
- package/lib/utils/ui.js +92 -0
- package/lib/utils/updates.js +9 -8
- package/package.json +2 -1
- package/templates/firebase/lib/features/home/home_page.dart +0 -19
- package/templates/firebase/lib/features/settings/ui/components/admin/admin_routes.dart +0 -1
- package/templates/firebase/lib/router.dart +0 -9
- package/templates/firebase/lib/features/dev/keyboard_test_page.dart +0 -93
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const kleur = require('kleur');
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const ui = require('../utils/ui');
|
|
5
|
+
const { printCompactHeader } = require('../utils/brand');
|
|
6
6
|
const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
|
|
7
7
|
const { slangGenerate } = require('../scaffold/shared/post-build');
|
|
8
8
|
|
|
9
|
-
const ora = oraPackage.default || oraPackage;
|
|
10
|
-
|
|
11
9
|
const SUPPORTED_LANGS = ['pt', 'en', 'es'];
|
|
12
10
|
|
|
13
11
|
/**
|
|
@@ -110,49 +108,43 @@ async function promptForTexts(projectDir, t, flags) {
|
|
|
110
108
|
};
|
|
111
109
|
}
|
|
112
110
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
},
|
|
145
|
-
]);
|
|
146
|
-
|
|
147
|
-
if (!response.demoTitle) {
|
|
148
|
-
throw new Error(t('notifications.error.cancelled'));
|
|
149
|
-
}
|
|
111
|
+
const cancel = () => { ui.cancel(t('notifications.error.cancelled')); process.exit(0); };
|
|
112
|
+
|
|
113
|
+
ui.log.step(kleur.bold(t('notifications.prompt.intro')));
|
|
114
|
+
ui.log.message(kleur.dim(t('notifications.prompt.hint')));
|
|
115
|
+
|
|
116
|
+
const required = (v) => (String(v || '').trim().length > 0 ? undefined : t('notifications.prompt.required'));
|
|
117
|
+
|
|
118
|
+
const demoTitle = await ui.text({
|
|
119
|
+
message: t('notifications.prompt.demoTitle'),
|
|
120
|
+
initialValue: flags.demoTitle || current.demoTitle,
|
|
121
|
+
validate: required,
|
|
122
|
+
onCancel: cancel,
|
|
123
|
+
});
|
|
124
|
+
const demoBody = await ui.text({
|
|
125
|
+
message: t('notifications.prompt.demoBody'),
|
|
126
|
+
initialValue: flags.demoBody || current.demoBody,
|
|
127
|
+
validate: required,
|
|
128
|
+
onCancel: cancel,
|
|
129
|
+
});
|
|
130
|
+
const reminderTitle = await ui.text({
|
|
131
|
+
message: t('notifications.prompt.reminderTitle'),
|
|
132
|
+
initialValue: flags.reminderTitle || current.reminderTitle,
|
|
133
|
+
validate: required,
|
|
134
|
+
onCancel: cancel,
|
|
135
|
+
});
|
|
136
|
+
const reminderBody = await ui.text({
|
|
137
|
+
message: t('notifications.prompt.reminderBody'),
|
|
138
|
+
initialValue: flags.reminderBody || current.reminderBody,
|
|
139
|
+
validate: required,
|
|
140
|
+
onCancel: cancel,
|
|
141
|
+
});
|
|
150
142
|
|
|
151
143
|
return {
|
|
152
|
-
demoTitle:
|
|
153
|
-
demoBody:
|
|
154
|
-
reminderTitle:
|
|
155
|
-
reminderBody:
|
|
144
|
+
demoTitle: String(demoTitle).trim(),
|
|
145
|
+
demoBody: String(demoBody).trim(),
|
|
146
|
+
reminderTitle: String(reminderTitle).trim(),
|
|
147
|
+
reminderBody: String(reminderBody).trim(),
|
|
156
148
|
};
|
|
157
149
|
}
|
|
158
150
|
|
|
@@ -169,6 +161,9 @@ async function runNotificationsText(directory, options = {}) {
|
|
|
169
161
|
await assertKasyProject(projectDir, t);
|
|
170
162
|
await assertLocalNotificationsEnabled(projectDir, t);
|
|
171
163
|
|
|
164
|
+
printCompactHeader(t);
|
|
165
|
+
ui.intro(t('notifications.prompt.intro'));
|
|
166
|
+
|
|
172
167
|
const targetLangs = resolveTargetLangs(options.lang);
|
|
173
168
|
const texts = await promptForTexts(
|
|
174
169
|
projectDir,
|
|
@@ -181,27 +176,32 @@ async function runNotificationsText(directory, options = {}) {
|
|
|
181
176
|
},
|
|
182
177
|
);
|
|
183
178
|
|
|
184
|
-
const writeSpinner =
|
|
179
|
+
const writeSpinner = ui.spinner();
|
|
180
|
+
writeSpinner.start(t('notifications.writing'));
|
|
185
181
|
await writeNotificationTexts(projectDir, targetLangs, texts);
|
|
186
|
-
writeSpinner.
|
|
182
|
+
writeSpinner.stop(t('notifications.written', { langs: targetLangs.join(', ') }));
|
|
187
183
|
|
|
188
|
-
const slangSpinner =
|
|
184
|
+
const slangSpinner = ui.spinner();
|
|
185
|
+
slangSpinner.start(t('notifications.slang'));
|
|
189
186
|
const slangResult = await slangGenerate(projectDir);
|
|
190
187
|
if (slangResult.ok) {
|
|
191
|
-
slangSpinner.
|
|
188
|
+
slangSpinner.stop(t('notifications.slangDone'));
|
|
192
189
|
} else {
|
|
193
|
-
slangSpinner.
|
|
194
|
-
|
|
190
|
+
slangSpinner.stop(`⚠ ${t('notifications.slangFailed')}`);
|
|
191
|
+
ui.log.message(kleur.dim('dart run slang'));
|
|
195
192
|
}
|
|
196
193
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
194
|
+
const summary = [
|
|
195
|
+
`${t('notifications.summary.demo')}`,
|
|
196
|
+
` ${kleur.white(texts.demoTitle)}`,
|
|
197
|
+
` ${kleur.white(texts.demoBody)}`,
|
|
198
|
+
`${t('notifications.summary.reminder')}`,
|
|
199
|
+
` ${kleur.white(texts.reminderTitle)}`,
|
|
200
|
+
` ${kleur.white(texts.reminderBody)}`,
|
|
201
|
+
].join('\n');
|
|
202
|
+
ui.note(summary);
|
|
203
|
+
|
|
204
|
+
ui.outro(t('notifications.done'));
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
module.exports = { runNotificationsText, readNotificationTexts, writeNotificationTexts };
|
package/lib/commands/remove.js
CHANGED
|
@@ -6,8 +6,8 @@ const path = require('node:path');
|
|
|
6
6
|
const fs = require('fs-extra');
|
|
7
7
|
const pkg = require('../../package.json');
|
|
8
8
|
const kleur = require('kleur');
|
|
9
|
-
const
|
|
10
|
-
const
|
|
9
|
+
const ui = require('../utils/ui');
|
|
10
|
+
const { printCompactHeader } = require('../utils/brand');
|
|
11
11
|
const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
|
|
12
12
|
const {
|
|
13
13
|
AVAILABLE_FEATURES,
|
|
@@ -29,7 +29,6 @@ const {
|
|
|
29
29
|
const { toPackageName } = require('../scaffold/backends/firebase/tokens');
|
|
30
30
|
|
|
31
31
|
const execAsync = promisify(exec);
|
|
32
|
-
const ora = oraPackage.default || oraPackage;
|
|
33
32
|
|
|
34
33
|
// ── Module metadata ──────────────────────────────────────────────────────────
|
|
35
34
|
|
|
@@ -299,7 +298,8 @@ async function runRemove(module, options = {}) {
|
|
|
299
298
|
const projectDir = path.resolve(options.directory || '.');
|
|
300
299
|
|
|
301
300
|
if (!module) {
|
|
302
|
-
|
|
301
|
+
printCompactHeader(t);
|
|
302
|
+
ui.log.warn(t('remove.error.noModule'));
|
|
303
303
|
return;
|
|
304
304
|
}
|
|
305
305
|
|
|
@@ -325,29 +325,28 @@ async function runRemove(module, options = {}) {
|
|
|
325
325
|
// 3. Check that the module is actually active
|
|
326
326
|
const activeModules = await getActiveModules(kitSetup, projectDir);
|
|
327
327
|
if (!activeModules.includes(normalized)) {
|
|
328
|
-
|
|
328
|
+
printCompactHeader(t);
|
|
329
|
+
ui.log.warn(t('remove.error.notActive', { module: normalized }));
|
|
329
330
|
return;
|
|
330
331
|
}
|
|
331
332
|
|
|
333
|
+
printCompactHeader(t);
|
|
334
|
+
ui.intro(t('remove.removing', { module: normalized }));
|
|
335
|
+
const cancel = () => { ui.cancel(t('remove.cancelled')); process.exit(0); };
|
|
336
|
+
|
|
332
337
|
// 4. Confirm before destructive action (skip with --yes)
|
|
333
338
|
if (!options.yes) {
|
|
334
|
-
const
|
|
335
|
-
{
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
initial: false,
|
|
340
|
-
},
|
|
341
|
-
{ onCancel: () => { throw new Error(t('remove.cancelled')); } }
|
|
342
|
-
);
|
|
339
|
+
const confirmed = await ui.confirm({
|
|
340
|
+
message: t('remove.confirm', { module: normalized }),
|
|
341
|
+
initialValue: false,
|
|
342
|
+
onCancel: cancel,
|
|
343
|
+
});
|
|
343
344
|
if (!confirmed) {
|
|
344
|
-
|
|
345
|
+
ui.outro(t('remove.cancelled'));
|
|
345
346
|
return;
|
|
346
347
|
}
|
|
347
348
|
}
|
|
348
349
|
|
|
349
|
-
console.log(kleur.bold(`\n${t('remove.removing', { module: normalized })}\n`));
|
|
350
|
-
|
|
351
350
|
// Build the module list that will be active AFTER removal (used for stub regen)
|
|
352
351
|
const modulesAfterRemoval = activeModules.filter((m) => m !== normalized);
|
|
353
352
|
|
|
@@ -391,7 +390,7 @@ async function runRemove(module, options = {}) {
|
|
|
391
390
|
await removePubspecDep(projectDir, 'sentry_flutter');
|
|
392
391
|
await writeNoOpSentryUsages(projectDir).catch(() => {});
|
|
393
392
|
} else if (normalized === 'sentry' && sentryStillNeeded) {
|
|
394
|
-
|
|
393
|
+
ui.log.message(kleur.dim(t('remove.warn.sentry.shared')));
|
|
395
394
|
}
|
|
396
395
|
|
|
397
396
|
// 10. Remove files and directories added by the module's patch
|
|
@@ -430,12 +429,13 @@ async function runRemove(module, options = {}) {
|
|
|
430
429
|
|
|
431
430
|
// 13. flutter pub get
|
|
432
431
|
{
|
|
433
|
-
const spinner =
|
|
432
|
+
const spinner = ui.spinner();
|
|
433
|
+
spinner.start(t('remove.pubGet'));
|
|
434
434
|
try {
|
|
435
435
|
await execAsync('flutter pub get', { cwd: projectDir, timeout: 300_000 });
|
|
436
|
-
spinner.
|
|
436
|
+
spinner.stop(t('remove.pubGetDone'));
|
|
437
437
|
} catch {
|
|
438
|
-
spinner.
|
|
438
|
+
spinner.stop(`⚠ ${t('remove.pubGetFailed')}`);
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
|
|
@@ -444,23 +444,24 @@ async function runRemove(module, options = {}) {
|
|
|
444
444
|
'revenuecat', 'analytics', 'sentry', 'onboarding', 'llm_chat', 'feedback',
|
|
445
445
|
].includes(normalized);
|
|
446
446
|
if (needsBuildRunner) {
|
|
447
|
-
const spinner =
|
|
447
|
+
const spinner = ui.spinner();
|
|
448
|
+
spinner.start(t('remove.buildRunner'));
|
|
448
449
|
try {
|
|
449
450
|
await execAsync(
|
|
450
451
|
'dart run build_runner build --delete-conflicting-outputs',
|
|
451
452
|
{ cwd: projectDir, timeout: 600_000 }
|
|
452
453
|
);
|
|
453
|
-
spinner.
|
|
454
|
+
spinner.stop(t('remove.buildRunnerDone'));
|
|
454
455
|
} catch {
|
|
455
|
-
spinner.
|
|
456
|
+
spinner.stop(`⚠ ${t('remove.buildRunnerFailed')}`);
|
|
456
457
|
}
|
|
457
458
|
}
|
|
458
459
|
|
|
459
|
-
console.log(kleur.green(`\n✓ ${t('remove.success', { module: normalized })}\n`));
|
|
460
|
-
|
|
461
460
|
if (normalized === 'ci') {
|
|
462
|
-
|
|
461
|
+
ui.log.message(kleur.dim(t('remove.warn.ci')));
|
|
463
462
|
}
|
|
463
|
+
|
|
464
|
+
ui.outro(t('remove.success', { module: normalized }));
|
|
464
465
|
}
|
|
465
466
|
|
|
466
467
|
module.exports = { runRemove };
|
package/lib/commands/run.js
CHANGED
|
@@ -3,6 +3,7 @@ const path = require('node:path');
|
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const kleur = require('kleur');
|
|
5
5
|
const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
|
|
6
|
+
const { printCompactHeader } = require('../utils/brand');
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Read dart-define args from .vscode/launch.json.
|
|
@@ -53,7 +54,8 @@ async function runRun(directory, options = {}) {
|
|
|
53
54
|
|
|
54
55
|
const args = ['run', ...deviceArgs, ...dartDefines];
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
printCompactHeader(t);
|
|
58
|
+
console.log(kleur.bold(`${t('run.launching')}`));
|
|
57
59
|
console.log(kleur.dim(` flutter ${args.join(' ')}`));
|
|
58
60
|
console.log(kleur.dim(` ✦ ${t('run.updateHint.prefix')} `) + kleur.cyan('kasy update') + kleur.dim(` ${t('run.updateHint.suffix')}\n`));
|
|
59
61
|
|