kasy-cli 1.32.0 → 1.34.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 (60) hide show
  1. package/bin/kasy.js +42 -0
  2. package/lib/commands/apple-web.js +222 -0
  3. package/lib/commands/configure.js +3 -91
  4. package/lib/commands/doctor.js +20 -0
  5. package/lib/commands/facebook.js +189 -0
  6. package/lib/commands/new.js +50 -2
  7. package/lib/scaffold/CHANGELOG.json +18 -0
  8. package/lib/scaffold/backends/firebase/setup-from-scratch.js +164 -0
  9. package/lib/scaffold/backends/supabase/deploy.js +92 -0
  10. package/lib/scaffold/backends/supabase/patch/lib/features/authentication/api/authentication_api.dart +10 -0
  11. package/lib/scaffold/shared/generator-utils.js +18 -6
  12. package/lib/utils/apple-web.js +147 -0
  13. package/lib/utils/facebook.js +162 -0
  14. package/lib/utils/i18n/messages-en.js +62 -0
  15. package/lib/utils/i18n/messages-es.js +62 -0
  16. package/lib/utils/i18n/messages-pt.js +62 -0
  17. package/package.json +2 -2
  18. package/templates/firebase/AGENTS.md +87 -0
  19. package/templates/firebase/CLAUDE.md +16 -0
  20. package/templates/firebase/DESIGN_SYSTEM.md +234 -0
  21. package/templates/firebase/docs/auth-setup.en.md +2 -2
  22. package/templates/firebase/docs/auth-setup.es.md +2 -2
  23. package/templates/firebase/docs/auth-setup.pt.md +2 -2
  24. package/templates/firebase/lib/components/components.dart +1 -0
  25. package/templates/firebase/lib/components/kasy_app_bar.dart +4 -1
  26. package/templates/firebase/lib/components/kasy_screen.dart +114 -0
  27. package/templates/firebase/lib/components/kasy_toast.dart +39 -70
  28. package/templates/firebase/lib/core/chrome/chrome_visibility.dart +22 -0
  29. package/templates/firebase/lib/core/config/features.dart +5 -0
  30. package/templates/firebase/lib/core/rating/widgets/review_popup.dart +46 -124
  31. package/templates/firebase/lib/core/widgets/update_bottom_sheet.dart +29 -126
  32. package/templates/firebase/lib/features/ai_chat/ai_chat_page.dart +11 -7
  33. package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_chat_composer.dart +21 -0
  34. package/templates/firebase/lib/features/ai_chat/ui/widgets/ai_conversation_list.dart +1 -1
  35. package/templates/firebase/lib/features/authentication/api/authentication_api.dart +61 -0
  36. package/templates/firebase/lib/features/authentication/ui/signin_page.dart +21 -15
  37. package/templates/firebase/lib/features/authentication/ui/signup_page.dart +20 -14
  38. package/templates/firebase/lib/features/feedbacks/ui/widgets/feature_card.dart +1 -2
  39. package/templates/firebase/lib/features/home/home_components_page.dart +7 -1
  40. package/templates/firebase/lib/features/home/home_components_preview_registry.dart +32 -0
  41. package/templates/firebase/lib/features/local_reminders/ui/reminder_page.dart +165 -209
  42. package/templates/firebase/lib/features/notifications/ui/components/notification_settings_sheet.dart +2 -2
  43. package/templates/firebase/lib/features/notifications/ui/components/notification_tile.dart +21 -8
  44. package/templates/firebase/lib/features/notifications/ui/components/push_notification_switcher.dart +2 -2
  45. package/templates/firebase/lib/features/notifications/ui/notifications_page.dart +3 -6
  46. package/templates/firebase/lib/features/notifications/ui/widgets/notification_tile.dart +77 -126
  47. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +3 -4
  48. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +2 -4
  49. package/templates/firebase/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +2 -1
  50. package/templates/firebase/lib/features/settings/ui/components/admin/admin_page.dart +17 -8
  51. package/templates/firebase/lib/features/settings/ui/components/avatar_component.dart +2 -2
  52. package/templates/firebase/lib/i18n/en.i18n.json +5 -4
  53. package/templates/firebase/lib/i18n/es.i18n.json +5 -4
  54. package/templates/firebase/lib/i18n/pt.i18n.json +5 -4
  55. package/templates/firebase/lib/router.dart +2 -0
  56. package/templates/firebase/pubspec.yaml +1 -1
  57. package/templates/firebase/tool/design_check.dart +152 -0
  58. package/templates/firebase/assets/images/review.png +0 -0
  59. package/templates/firebase/assets/images/update.png +0 -0
  60. package/templates/firebase/lib/features/notifications/ui/components/notifications_header.dart +0 -32
@@ -0,0 +1,152 @@
1
+ // Kasy design-system guard-rail.
2
+ //
3
+ // Fails (exit 1) when a FEATURE SCREEN reaches around the design system and
4
+ // hardcodes a value that should come from a token / component. The design
5
+ // primitives themselves (lib/components, lib/core) are exempt — that is where
6
+ // the system is built, so raw values are expected there.
7
+ //
8
+ // This is intentionally a plain script, not a hidden dependency: read it, tune
9
+ // the lists below, or delete it. It enforces the project's *defaults*; it never
10
+ // locks anyone in.
11
+ //
12
+ // Run it locally or in CI:
13
+ // dart run tool/design_check.dart
14
+ //
15
+ // Escape hatch for a deliberate one-off: put `// design-check: ignore` on the
16
+ // offending line (the reason should be obvious from a nearby comment).
17
+ //
18
+ // See DESIGN_SYSTEM.md for the tokens/roles to use instead.
19
+
20
+ import 'dart:io';
21
+
22
+ /// The guard-rail only scans FEATURE SCREENS ([_scanRoot]). The design system
23
+ /// itself (lib/components, lib/core) and the app bootstrap (lib/main.dart) are
24
+ /// the *implementation* of the system, so raw values are expected there and are
25
+ /// out of scope by construction.
26
+ const String _scanRoot = 'lib/features';
27
+
28
+ /// Path fragments that are exempt even inside the feature layer.
29
+ /// - admin: internal admin tooling (kept out of the product design pass).
30
+ /// - generated files: not authored by hand.
31
+ /// - showcase/mockups: deliberately render raw values to demo them.
32
+ /// - subscriptions: the paywall is mid-redesign; re-enable when it lands.
33
+ const List<String> _exemptPathFragments = <String>[
34
+ '/admin/',
35
+ 'admin_card.dart',
36
+ '.g.dart',
37
+ '.freezed.dart',
38
+ 'home_components_preview_registry.dart',
39
+ 'home_components_preview_page.dart',
40
+ 'home_components_page.dart',
41
+ 'design_system_page.dart',
42
+ 'onboarding_module_mockups.dart',
43
+ '/features/subscriptions/',
44
+ ];
45
+
46
+ const String _ignoreMarker = '// design-check: ignore';
47
+
48
+ class _Rule {
49
+ const _Rule(this.id, this.pattern, this.message);
50
+ final String id;
51
+ final RegExp pattern;
52
+ final String message;
53
+
54
+ /// Optional secondary token that must ALSO be on the line for the rule to
55
+ /// fire (used to scope `size:` to Icon lines only).
56
+ bool matches(String line) => pattern.hasMatch(line);
57
+ }
58
+
59
+ final List<_Rule> _rules = <_Rule>[
60
+ _Rule(
61
+ 'raw-material',
62
+ RegExp(r'\b(ElevatedButton|OutlinedButton|TextButton|AlertDialog|SnackBar)\s*\(|(?<![A-Za-z])Card\s*\('),
63
+ 'Use the Kasy component (KasyButton / showKasyConfirmDialog / showKasyToast '
64
+ '/ KasyCard) instead of the raw Material widget.',
65
+ ),
66
+ _Rule(
67
+ 'hardcoded-font-size',
68
+ RegExp(r'fontSize:\s*\d'),
69
+ 'Use a typography role (context.textTheme.* / KasyTextTheme.*) instead of a '
70
+ 'literal fontSize.',
71
+ ),
72
+ _Rule(
73
+ 'raw-color',
74
+ // `Color(0x...)` literals, or `Colors.<named>` — but NOT `KasyColors.` (the
75
+ // token class, hence the lookbehind) and NOT the transparent / white* /
76
+ // black* helpers, which are the legitimate way to build scrims & overlays.
77
+ RegExp(r'Color\(0x|(?<![A-Za-z])Colors\.(?!transparent\b)(?!white)(?!black)[A-Za-z]'),
78
+ 'Use a colour token (context.colors.*) instead of a raw Color/Colors value.',
79
+ ),
80
+ ];
81
+
82
+ // The icon rule needs two signals on the same line, so it is handled separately.
83
+ final RegExp _iconCall = RegExp(r'\bIcon\s*\(');
84
+ final RegExp _numericSize = RegExp(r'size:\s*\d');
85
+
86
+ bool _isExempt(String path) =>
87
+ _exemptPathFragments.any((String frag) => path.contains(frag));
88
+
89
+ void main() {
90
+ final Directory libDir = Directory(_scanRoot);
91
+ if (!libDir.existsSync()) {
92
+ stderr.writeln('design_check: run me from the package root (no $_scanRoot here).');
93
+ exit(2);
94
+ }
95
+
96
+ final List<String> violations = <String>[];
97
+ int scanned = 0;
98
+
99
+ for (final FileSystemEntity entity in libDir.listSync(recursive: true)) {
100
+ if (entity is! File || !entity.path.endsWith('.dart')) continue;
101
+ final String path = entity.path.replaceAll(r'\', '/');
102
+ if (_isExempt('/$path')) continue;
103
+ scanned++;
104
+
105
+ final List<String> lines = entity.readAsLinesSync();
106
+ for (int i = 0; i < lines.length; i++) {
107
+ final String line = lines[i];
108
+ if (line.contains(_ignoreMarker)) continue;
109
+ final String code = _stripComment(line);
110
+ if (code.trim().isEmpty) continue;
111
+
112
+ for (final _Rule rule in _rules) {
113
+ if (rule.matches(code)) {
114
+ violations.add(_format(path, i + 1, rule.id, rule.message, line));
115
+ }
116
+ }
117
+ if (_iconCall.hasMatch(code) && _numericSize.hasMatch(code)) {
118
+ violations.add(_format(
119
+ path,
120
+ i + 1,
121
+ 'hardcoded-icon-size',
122
+ 'Use a KasyIconSize.* token instead of a literal Icon size.',
123
+ line,
124
+ ));
125
+ }
126
+ }
127
+ }
128
+
129
+ if (violations.isEmpty) {
130
+ stdout.writeln('design_check: OK ($scanned feature files clean).');
131
+ exit(0);
132
+ }
133
+
134
+ stdout.writeln('design_check: ${violations.length} violation(s) found.\n');
135
+ stdout.writeln(violations.join('\n\n'));
136
+ stdout.writeln(
137
+ '\nFix by using a token/role/component (see DESIGN_SYSTEM.md), or mark a '
138
+ 'deliberate exception with `$_ignoreMarker` on the line.',
139
+ );
140
+ exit(1);
141
+ }
142
+
143
+ /// Drops an end-of-line `//` comment so rules don't match commented-out code or
144
+ /// doc text (keeps string literals intact enough for these coarse checks).
145
+ String _stripComment(String line) {
146
+ final int idx = line.indexOf('//');
147
+ return idx == -1 ? line : line.substring(0, idx);
148
+ }
149
+
150
+ String _format(String path, int line, String id, String message, String src) {
151
+ return ' $path:$line [$id]\n ${src.trim()}\n → $message';
152
+ }
@@ -1,32 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_riverpod/flutter_riverpod.dart';
3
- import 'package:kasy_kit/core/theme/theme.dart';
4
- import 'package:kasy_kit/i18n/translations.g.dart';
5
-
6
- class NotificationsHeader extends ConsumerWidget {
7
- final double? paddingHeight;
8
-
9
- const NotificationsHeader({super.key, this.paddingHeight});
10
-
11
- @override
12
- Widget build(BuildContext context, WidgetRef ref) {
13
- return Padding(
14
- padding: EdgeInsets.fromLTRB(
15
- KasySpacing.lg,
16
- paddingHeight ?? KasySpacing.smd,
17
- KasySpacing.lg,
18
- KasySpacing.md,
19
- ),
20
- child: Row(
21
- children: [
22
- Text(
23
- t.navigation.notifications,
24
- style: context.textTheme.headlineMedium!.copyWith(
25
- color: context.colors.onSurface,
26
- ),
27
- ),
28
- ],
29
- ),
30
- );
31
- }
32
- }