@_nazmiforreal/flutter-ota 0.1.20 → 0.1.22
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/flutter-ota-linux-x64 +0 -0
- package/dart-src/packages/cli-tools/.dart_tool/package_config.json +1 -1
- package/dart-src/packages/cli-tools/.dart_tool/package_graph.json +340 -340
- package/dart-src/packages/cli-tools/lib/flutter_ota_kit_cli.dart +9 -5
- package/dart-src/packages/cli-tools/lib/src/cli_base.dart +3 -2
- package/dart-src/packages/cli-tools/lib/src/commands/bundle.dart +106 -31
- package/dart-src/packages/cli-tools/lib/src/commands/channel.dart +34 -7
- package/dart-src/packages/cli-tools/lib/src/commands/config_command.dart +12 -4
- package/dart-src/packages/cli-tools/lib/src/commands/console.dart +7 -8
- package/dart-src/packages/cli-tools/lib/src/commands/deploy.dart +41 -9
- package/dart-src/packages/cli-tools/lib/src/commands/doctor.dart +124 -13
- package/dart-src/packages/cli-tools/lib/src/commands/fingerprint.dart +2 -1
- package/dart-src/packages/cli-tools/lib/src/commands/init.dart +58 -28
- package/dart-src/packages/cli-tools/lib/src/commands/keys.dart +11 -5
- package/dart-src/packages/cli-tools/lib/src/commands/migrate.dart +283 -32
- package/dart-src/packages/cli-tools/lib/src/commands/pocketbase.dart +347 -121
- package/dart-src/packages/cli-tools/lib/src/commands/rollback.dart +18 -9
- package/dart-src/packages/cli-tools/lib/src/commands/storage.dart +32 -15
- package/dart-src/packages/cli-tools/lib/src/config.dart +16 -22
- package/dart-src/packages/cli-tools/lib/src/operations.dart +1 -3
- package/dart-src/packages/cli-tools/lib/src/pocketbase/process_manager.dart +26 -17
- package/dart-src/packages/cli-tools/lib/src/pocketbase/schema_installer.dart +0 -1
- package/dart-src/packages/cli-tools/lib/src/runner.dart +3 -1
- package/dart-src/packages/cli-tools/lib/src/ui/ui.dart +10 -16
- package/dart-src/packages/cli-tools/pubspec.lock +7 -7
- package/dart-src/packages/cli-tools/test/mocks/mock_pocketbase_client.dart +7 -3
- package/dart-src/packages/cli-tools/test/pocketbase_schema_test.dart +13 -16
- package/dart-src/packages/core/CHANGELOG.md +15 -0
- package/dart-src/packages/core/lib/flutter_ota_kit_core.dart +2 -0
- package/dart-src/packages/core/lib/src/app_update_info.dart +71 -1
- package/dart-src/packages/core/lib/src/bundle.dart +59 -17
- package/dart-src/packages/core/lib/src/bundle_artifacts.dart +7 -3
- package/dart-src/packages/core/lib/src/bundle_patch_artifact.dart +16 -0
- package/dart-src/packages/core/lib/src/changed_asset.dart +33 -3
- package/dart-src/packages/core/lib/src/get_bundles_args.dart +24 -2
- package/dart-src/packages/core/lib/src/platform.dart +8 -0
- package/dart-src/packages/core/lib/src/semver.dart +0 -3
- package/dart-src/packages/core/lib/src/status.dart +20 -1
- package/dart-src/packages/core/lib/src/strategy.dart +10 -0
- package/dart-src/packages/core/lib/src/update_bundle_params.dart +15 -0
- package/dart-src/packages/core/lib/src/uuid.dart +11 -0
- package/dart-src/packages/core/pubspec.yaml +1 -1
- package/dart-src/plugins/aws/CHANGELOG.md +18 -0
- package/dart-src/plugins/aws/lib/src/aws_cloudfront_client.dart +0 -1
- package/dart-src/plugins/aws/pubspec.yaml +3 -3
- package/dart-src/plugins/cloudflare/CHANGELOG.md +18 -0
- package/dart-src/plugins/cloudflare/pubspec.yaml +3 -3
- package/dart-src/plugins/plugin-core/CHANGELOG.md +15 -0
- package/dart-src/plugins/plugin-core/lib/src/asset_storage_layout.dart +3 -0
- package/dart-src/plugins/plugin-core/lib/src/parse_storage_uri.dart +17 -0
- package/dart-src/plugins/plugin-core/lib/src/types.dart +94 -3
- package/dart-src/plugins/plugin-core/pubspec.yaml +2 -2
- package/dart-src/plugins/pocketbase/CHANGELOG.md +18 -0
- package/dart-src/plugins/pocketbase/lib/src/pocketbase_client.dart +3 -0
- package/dart-src/plugins/pocketbase/pubspec.yaml +3 -3
- package/dart-src/plugins/postgres/CHANGELOG.md +18 -0
- package/dart-src/plugins/postgres/pubspec.yaml +3 -3
- package/dart-src/plugins/supabase/CHANGELOG.md +18 -0
- package/dart-src/plugins/supabase/pubspec.yaml +3 -3
- package/package.json +2 -2
- package/scripts/postinstall.js +5 -1
- package/bin/flutter-ota.js +0 -36
|
@@ -18,7 +18,7 @@ import '../pocketbase/schema_installer.dart';
|
|
|
18
18
|
import '../ui/ui.dart';
|
|
19
19
|
|
|
20
20
|
class PocketBaseCommand extends FlutterPatcherCommand {
|
|
21
|
-
|
|
21
|
+
PocketBaseCommand() {
|
|
22
22
|
addSubcommand(PocketBaseInstallCommand());
|
|
23
23
|
addSubcommand(PocketBaseServeCommand());
|
|
24
24
|
addSubcommand(PocketBaseStopCommand());
|
|
@@ -46,7 +46,7 @@ class PocketBaseCommand extends FlutterPatcherCommand {
|
|
|
46
46
|
String get description =>
|
|
47
47
|
'Manage a local PocketBase instance (install / serve / stop / '
|
|
48
48
|
'status / backup / export / import / admin / migrate / health / '
|
|
49
|
-
'logs / records / collections / settings / sql / crons).';
|
|
49
|
+
'logs / records / collections / settings / sql / crons / query / config).';
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
class PocketBaseInstallCommand extends FlutterPatcherCommand {
|
|
@@ -91,7 +91,11 @@ class PocketBaseServeCommand extends FlutterPatcherCommand {
|
|
|
91
91
|
PocketBaseServeCommand() {
|
|
92
92
|
argParser.addOption('version', help: 'PocketBase version.');
|
|
93
93
|
argParser.addOption('port', help: 'PB HTTP port.', defaultsTo: '8090');
|
|
94
|
-
argParser.addOption(
|
|
94
|
+
argParser.addOption(
|
|
95
|
+
'host',
|
|
96
|
+
help: 'PB bind address.',
|
|
97
|
+
defaultsTo: '127.0.0.1',
|
|
98
|
+
);
|
|
95
99
|
argParser.addOption('data-dir', help: 'PB data directory.');
|
|
96
100
|
argParser.addOption('admin-email', help: 'Bootstrap admin email.');
|
|
97
101
|
argParser.addOption('admin-password', help: 'Bootstrap admin password.');
|
|
@@ -225,18 +229,36 @@ class PocketBaseServeCommand extends FlutterPatcherCommand {
|
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
class PocketBaseStopCommand extends FlutterPatcherCommand {
|
|
232
|
+
PocketBaseStopCommand() {
|
|
233
|
+
argParser.addOption('port', help: 'HTTP port.', defaultsTo: '8090');
|
|
234
|
+
argParser.addOption('host', help: 'Bind address.', defaultsTo: '127.0.0.1');
|
|
235
|
+
}
|
|
236
|
+
|
|
228
237
|
@override
|
|
229
238
|
String get name => 'stop';
|
|
230
239
|
|
|
231
240
|
@override
|
|
232
|
-
String get description =>
|
|
233
|
-
'Hint to stop a running PocketBase (Ctrl+C in serve).';
|
|
241
|
+
String get description => 'Stop a running PocketBase instance.';
|
|
234
242
|
|
|
235
243
|
@override
|
|
236
244
|
Future<int> run() => runGuarded(() async {
|
|
237
245
|
banner('pocketbase · stop');
|
|
238
|
-
|
|
239
|
-
|
|
246
|
+
final port = int.tryParse(argResults!['port'] as String? ?? '8090') ?? 8090;
|
|
247
|
+
final host = argResults!['host'] as String? ?? '127.0.0.1';
|
|
248
|
+
final mgr = PocketBaseProcessManager(
|
|
249
|
+
binaryPath: PocketBaseInstallPaths.resolve().binaryPath,
|
|
250
|
+
dataDir: PocketBaseInstallPaths.resolve().installDir,
|
|
251
|
+
port: port,
|
|
252
|
+
host: host,
|
|
253
|
+
);
|
|
254
|
+
final pid = mgr.readPid();
|
|
255
|
+
if (pid <= 0) {
|
|
256
|
+
step('No PocketBase process found.');
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
step('Stopping PocketBase (PID $pid)...');
|
|
260
|
+
await mgr.stop();
|
|
261
|
+
step('PocketBase stopped.');
|
|
240
262
|
});
|
|
241
263
|
}
|
|
242
264
|
|
|
@@ -281,7 +303,10 @@ class PocketBaseStatusCommand extends FlutterPatcherCommand {
|
|
|
281
303
|
box('status', [
|
|
282
304
|
kv('version', paths.version),
|
|
283
305
|
kv('binary', exists ? green('installed') : red('not installed')),
|
|
284
|
-
kv(
|
|
306
|
+
kv(
|
|
307
|
+
'pid',
|
|
308
|
+
pidAlive ? green('$pid') : (pid > 0 ? yellow('$pid (dead)') : dim('-')),
|
|
309
|
+
),
|
|
285
310
|
kv('health', healthy ? green('healthy') : red('unreachable')),
|
|
286
311
|
kv('url', 'http://$host:$port'),
|
|
287
312
|
]);
|
|
@@ -300,7 +325,14 @@ void _addBackendOptions(ArgParser parser) {
|
|
|
300
325
|
parser.addOption('data-dir', help: 'PB data directory.');
|
|
301
326
|
}
|
|
302
327
|
|
|
303
|
-
|
|
328
|
+
String _safeSubstring(String? s, int length) {
|
|
329
|
+
if (s == null || s.isEmpty) return '';
|
|
330
|
+
return s.length > length ? s.substring(0, length) : s;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
(String url, String adminEmail, String adminPassword) _resolveBackend(
|
|
334
|
+
ArgResults r,
|
|
335
|
+
) {
|
|
304
336
|
final url = r['url'] as String? ?? _detectRunningUrl(r);
|
|
305
337
|
if (url == null || url.isEmpty) {
|
|
306
338
|
throw const PackException(
|
|
@@ -308,10 +340,12 @@ void _addBackendOptions(ArgParser parser) {
|
|
|
308
340
|
64,
|
|
309
341
|
);
|
|
310
342
|
}
|
|
311
|
-
final admin =
|
|
343
|
+
final admin =
|
|
344
|
+
r['admin-email'] as String? ??
|
|
312
345
|
Platform.environment['POCKETBASE_ADMIN_EMAIL'] ??
|
|
313
346
|
'';
|
|
314
|
-
final pass =
|
|
347
|
+
final pass =
|
|
348
|
+
r['admin-password'] as String? ??
|
|
315
349
|
Platform.environment['POCKETBASE_ADMIN_PASSWORD'] ??
|
|
316
350
|
'';
|
|
317
351
|
if (admin.isEmpty || pass.isEmpty) {
|
|
@@ -464,7 +498,11 @@ class PocketBaseBackupDeleteCommand extends FlutterPatcherCommand {
|
|
|
464
498
|
class PocketBaseBackupRestoreCommand extends FlutterPatcherCommand {
|
|
465
499
|
PocketBaseBackupRestoreCommand() {
|
|
466
500
|
_addBackendOptions(argParser);
|
|
467
|
-
argParser.addOption(
|
|
501
|
+
argParser.addOption(
|
|
502
|
+
'name',
|
|
503
|
+
help: 'Backup key to restore.',
|
|
504
|
+
mandatory: true,
|
|
505
|
+
);
|
|
468
506
|
}
|
|
469
507
|
|
|
470
508
|
@override
|
|
@@ -485,7 +523,11 @@ class PocketBaseBackupRestoreCommand extends FlutterPatcherCommand {
|
|
|
485
523
|
class PocketBaseBackupDownloadCommand extends FlutterPatcherCommand {
|
|
486
524
|
PocketBaseBackupDownloadCommand() {
|
|
487
525
|
_addBackendOptions(argParser);
|
|
488
|
-
argParser.addOption(
|
|
526
|
+
argParser.addOption(
|
|
527
|
+
'name',
|
|
528
|
+
help: 'Backup key to download.',
|
|
529
|
+
mandatory: true,
|
|
530
|
+
);
|
|
489
531
|
argParser.addOption('output', help: 'Output directory.', defaultsTo: '.');
|
|
490
532
|
}
|
|
491
533
|
|
|
@@ -500,16 +542,20 @@ class PocketBaseBackupDownloadCommand extends FlutterPatcherCommand {
|
|
|
500
542
|
banner('pocketbase · backup · download');
|
|
501
543
|
final key = argResults!['name'] as String;
|
|
502
544
|
final output = argResults!['output'] as String;
|
|
503
|
-
final
|
|
504
|
-
final (url, _, _) = _resolveBackend(argResults!);
|
|
545
|
+
final (url, admin, pass) = _resolveBackend(argResults!);
|
|
505
546
|
final dlClient = PocketBaseClient(url);
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
547
|
+
try {
|
|
548
|
+
await dlClient.authenticate(admin, pass);
|
|
549
|
+
final token = dlClient.authToken;
|
|
550
|
+
final dlUrl = dlClient.backupDownloadUrl(key, token);
|
|
551
|
+
final bytes = await dlClient.downloadFileUnauth(dlUrl);
|
|
552
|
+
final out = File(p.join(output, key));
|
|
553
|
+
await out.parent.create(recursive: true);
|
|
554
|
+
await out.writeAsBytes(bytes);
|
|
555
|
+
step(green('Saved to ${out.path}'));
|
|
556
|
+
} finally {
|
|
557
|
+
dlClient.close();
|
|
558
|
+
}
|
|
513
559
|
});
|
|
514
560
|
}
|
|
515
561
|
|
|
@@ -566,39 +612,48 @@ class PocketBaseExportCommand extends FlutterPatcherCommand {
|
|
|
566
612
|
final collection = r['collection'] as String?;
|
|
567
613
|
final output = r['output'] as String;
|
|
568
614
|
|
|
569
|
-
final
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
collections
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
final
|
|
579
|
-
|
|
580
|
-
|
|
615
|
+
final (url, admin, pass) = _resolveBackend(r);
|
|
616
|
+
final client = PocketBaseClient(url);
|
|
617
|
+
try {
|
|
618
|
+
await client.authenticate(admin, pass);
|
|
619
|
+
|
|
620
|
+
final collections = <String>[];
|
|
621
|
+
if (collection != null && collection.isNotEmpty) {
|
|
622
|
+
collections.add(collection);
|
|
623
|
+
} else {
|
|
624
|
+
final all = await client.listCollections();
|
|
625
|
+
for (final c in all) {
|
|
626
|
+
final name = c['name'] as String? ?? '';
|
|
627
|
+
if (name.isNotEmpty && !name.startsWith('_') && c['system'] != true) {
|
|
628
|
+
collections.add(name);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (collections.isEmpty) {
|
|
632
|
+
collections.addAll([
|
|
633
|
+
'bundles',
|
|
634
|
+
'channels',
|
|
635
|
+
'audit_log',
|
|
636
|
+
'bundles_patches',
|
|
637
|
+
]);
|
|
581
638
|
}
|
|
582
639
|
}
|
|
583
|
-
if (collections.isEmpty) {
|
|
584
|
-
collections.addAll(['bundles', 'channels', 'audit_log', 'bundles_patches']);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
640
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
641
|
+
for (final c in collections) {
|
|
642
|
+
try {
|
|
643
|
+
final records = await client.exportCollection(c);
|
|
644
|
+
final outFile = File(p.join(output, '$c.json'));
|
|
645
|
+
await outFile.parent.create(recursive: true);
|
|
646
|
+
await outFile.writeAsString(
|
|
647
|
+
const JsonEncoder.withIndent(' ').convert(records),
|
|
648
|
+
);
|
|
649
|
+
step('${records.length} records → ${outFile.path}');
|
|
650
|
+
} catch (e) {
|
|
651
|
+
warn('Failed to export $c: $e');
|
|
652
|
+
}
|
|
599
653
|
}
|
|
654
|
+
} finally {
|
|
655
|
+
client.close();
|
|
600
656
|
}
|
|
601
|
-
client.close();
|
|
602
657
|
});
|
|
603
658
|
}
|
|
604
659
|
|
|
@@ -613,7 +668,8 @@ class PocketBaseImportCommand extends FlutterPatcherCommand {
|
|
|
613
668
|
String get name => 'import';
|
|
614
669
|
|
|
615
670
|
@override
|
|
616
|
-
String get description =>
|
|
671
|
+
String get description =>
|
|
672
|
+
'Import records from a JSON file into a collection.';
|
|
617
673
|
|
|
618
674
|
@override
|
|
619
675
|
Future<int> run() => runGuarded(() async {
|
|
@@ -674,10 +730,14 @@ class PocketBaseAdminCreateCommand extends FlutterPatcherCommand {
|
|
|
674
730
|
final password = r['password'] as String;
|
|
675
731
|
final result = await _pbStep(
|
|
676
732
|
'Creating admin $email',
|
|
677
|
-
(c) => c.createAdmin(
|
|
733
|
+
(c) => c.createAdmin(
|
|
734
|
+
email: email,
|
|
735
|
+
password: password,
|
|
736
|
+
passwordConfirm: password,
|
|
737
|
+
),
|
|
678
738
|
r,
|
|
679
739
|
);
|
|
680
|
-
|
|
740
|
+
stdout.writeln(' ${dim('→')} admin ${cyan(result['id'] ?? '?')} $email');
|
|
681
741
|
});
|
|
682
742
|
}
|
|
683
743
|
|
|
@@ -695,13 +755,22 @@ class PocketBaseAdminListCommand extends FlutterPatcherCommand {
|
|
|
695
755
|
@override
|
|
696
756
|
Future<int> run() => runGuarded(() async {
|
|
697
757
|
banner('pocketbase · admin · list');
|
|
698
|
-
final admins = await _pbStep(
|
|
758
|
+
final admins = await _pbStep(
|
|
759
|
+
'Listing admins',
|
|
760
|
+
(c) => c.listAdmins(),
|
|
761
|
+
argResults!,
|
|
762
|
+
);
|
|
699
763
|
if (admins.isEmpty) {
|
|
700
764
|
warn('No admins found.');
|
|
701
765
|
return;
|
|
702
766
|
}
|
|
703
767
|
final rows = admins
|
|
704
|
-
.map(
|
|
768
|
+
.map(
|
|
769
|
+
(a) => [
|
|
770
|
+
cyan(a['id']?.toString() ?? '?'),
|
|
771
|
+
a['email']?.toString() ?? '?',
|
|
772
|
+
],
|
|
773
|
+
)
|
|
705
774
|
.toList();
|
|
706
775
|
table('${admins.length} admins', ['ID', 'EMAIL'], rows);
|
|
707
776
|
});
|
|
@@ -711,7 +780,11 @@ class PocketBaseAdminUpdateCommand extends FlutterPatcherCommand {
|
|
|
711
780
|
PocketBaseAdminUpdateCommand() {
|
|
712
781
|
_addBackendOptions(argParser);
|
|
713
782
|
argParser.addOption('id', help: 'Admin ID to update.', mandatory: true);
|
|
714
|
-
argParser.addOption(
|
|
783
|
+
argParser.addOption(
|
|
784
|
+
'body',
|
|
785
|
+
help: 'JSON fields to update.',
|
|
786
|
+
mandatory: true,
|
|
787
|
+
);
|
|
715
788
|
}
|
|
716
789
|
|
|
717
790
|
@override
|
|
@@ -804,15 +877,18 @@ class PocketBaseHealthCommand extends FlutterPatcherCommand {
|
|
|
804
877
|
@override
|
|
805
878
|
Future<int> run() => runGuarded(() async {
|
|
806
879
|
banner('pocketbase · health');
|
|
807
|
-
final health = await _pbStep(
|
|
880
|
+
final health = await _pbStep(
|
|
881
|
+
'health',
|
|
882
|
+
(c) => c.healthDetailed(),
|
|
883
|
+
argResults!,
|
|
884
|
+
);
|
|
808
885
|
final code = health['code'] as int? ?? 0;
|
|
809
886
|
final message = health['message'] as String? ?? '';
|
|
810
887
|
final data = health['data'] as Map<String, dynamic>? ?? {};
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
]);
|
|
888
|
+
final status = code == 200 ? green('healthy') : red('unhealthy');
|
|
889
|
+
step('status $status');
|
|
890
|
+
step('message $message');
|
|
891
|
+
step('canBackup ${data['canBackup'] ?? false}');
|
|
816
892
|
});
|
|
817
893
|
}
|
|
818
894
|
|
|
@@ -871,11 +947,15 @@ class PocketBaseLogsListCommand extends FlutterPatcherCommand {
|
|
|
871
947
|
}
|
|
872
948
|
final rows = items.map((log) {
|
|
873
949
|
final level = log['level'] as int? ?? 0;
|
|
874
|
-
final lvl = level == 0
|
|
950
|
+
final lvl = level == 0
|
|
951
|
+
? green('INFO')
|
|
952
|
+
: level == 1
|
|
953
|
+
? yellow('WARN')
|
|
954
|
+
: red('ERROR');
|
|
875
955
|
final msg = (log['message'] as String? ?? '').length > 60
|
|
876
956
|
? '${(log['message'] as String).substring(0, 57)}...'
|
|
877
957
|
: log['message'] as String? ?? '';
|
|
878
|
-
return [lvl, log['created']?.toString()
|
|
958
|
+
return [lvl, _safeSubstring(log['created']?.toString(), 19), msg];
|
|
879
959
|
}).toList();
|
|
880
960
|
table('$total logs', ['LEVEL', 'TIME', 'MESSAGE'], rows);
|
|
881
961
|
});
|
|
@@ -905,10 +985,14 @@ class PocketBaseLogsStatsCommand extends FlutterPatcherCommand {
|
|
|
905
985
|
warn('No stats available.');
|
|
906
986
|
return;
|
|
907
987
|
}
|
|
908
|
-
final rows = stats
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
988
|
+
final rows = stats
|
|
989
|
+
.map(
|
|
990
|
+
(s) => [
|
|
991
|
+
_safeSubstring(s['date']?.toString(), 16),
|
|
992
|
+
'${s['total'] ?? 0}',
|
|
993
|
+
],
|
|
994
|
+
)
|
|
995
|
+
.toList();
|
|
912
996
|
table('${stats.length} entries', ['TIME', 'COUNT'], rows);
|
|
913
997
|
});
|
|
914
998
|
}
|
|
@@ -956,7 +1040,11 @@ class PocketBaseRecordsCommand extends FlutterPatcherCommand {
|
|
|
956
1040
|
class PocketBaseRecordsListCommand extends FlutterPatcherCommand {
|
|
957
1041
|
PocketBaseRecordsListCommand() {
|
|
958
1042
|
_addBackendOptions(argParser);
|
|
959
|
-
argParser.addOption(
|
|
1043
|
+
argParser.addOption(
|
|
1044
|
+
'collection',
|
|
1045
|
+
help: 'Collection name.',
|
|
1046
|
+
mandatory: true,
|
|
1047
|
+
);
|
|
960
1048
|
argParser.addOption('filter', help: 'PB filter expression.');
|
|
961
1049
|
argParser.addOption('sort', help: 'Sort field.');
|
|
962
1050
|
argParser.addOption('page', help: 'Page number.', defaultsTo: '1');
|
|
@@ -991,16 +1079,25 @@ class PocketBaseRecordsListCommand extends FlutterPatcherCommand {
|
|
|
991
1079
|
}
|
|
992
1080
|
final rows = data.items.map((r) {
|
|
993
1081
|
final m = r as Map<String, dynamic>;
|
|
994
|
-
|
|
1082
|
+
final label =
|
|
1083
|
+
m['name']?.toString() ??
|
|
1084
|
+
m['updated']?.toString() ??
|
|
1085
|
+
m['created']?.toString() ??
|
|
1086
|
+
'';
|
|
1087
|
+
return [cyan(m['id']?.toString() ?? '?'), label];
|
|
995
1088
|
}).toList();
|
|
996
|
-
table('${data.totalItems} records', ['ID', '
|
|
1089
|
+
table('${data.totalItems} records', ['ID', 'LABEL'], rows);
|
|
997
1090
|
});
|
|
998
1091
|
}
|
|
999
1092
|
|
|
1000
1093
|
class PocketBaseRecordsGetCommand extends FlutterPatcherCommand {
|
|
1001
1094
|
PocketBaseRecordsGetCommand() {
|
|
1002
1095
|
_addBackendOptions(argParser);
|
|
1003
|
-
argParser.addOption(
|
|
1096
|
+
argParser.addOption(
|
|
1097
|
+
'collection',
|
|
1098
|
+
help: 'Collection name.',
|
|
1099
|
+
mandatory: true,
|
|
1100
|
+
);
|
|
1004
1101
|
argParser.addOption('id', help: 'Record ID.', mandatory: true);
|
|
1005
1102
|
}
|
|
1006
1103
|
|
|
@@ -1016,7 +1113,11 @@ class PocketBaseRecordsGetCommand extends FlutterPatcherCommand {
|
|
|
1016
1113
|
final r = argResults!;
|
|
1017
1114
|
final record = await _pbStep(
|
|
1018
1115
|
'Getting ${r['collection']}/${r['id']}',
|
|
1019
|
-
(c) => c.getRecord<dynamic>(
|
|
1116
|
+
(c) => c.getRecord<dynamic>(
|
|
1117
|
+
r['collection'] as String,
|
|
1118
|
+
r['id'] as String,
|
|
1119
|
+
(j) => j,
|
|
1120
|
+
),
|
|
1020
1121
|
r,
|
|
1021
1122
|
);
|
|
1022
1123
|
if (record == null) {
|
|
@@ -1030,7 +1131,11 @@ class PocketBaseRecordsGetCommand extends FlutterPatcherCommand {
|
|
|
1030
1131
|
class PocketBaseRecordsCreateCommand extends FlutterPatcherCommand {
|
|
1031
1132
|
PocketBaseRecordsCreateCommand() {
|
|
1032
1133
|
_addBackendOptions(argParser);
|
|
1033
|
-
argParser.addOption(
|
|
1134
|
+
argParser.addOption(
|
|
1135
|
+
'collection',
|
|
1136
|
+
help: 'Collection name.',
|
|
1137
|
+
mandatory: true,
|
|
1138
|
+
);
|
|
1034
1139
|
argParser.addOption('body', help: 'JSON body.', mandatory: true);
|
|
1035
1140
|
}
|
|
1036
1141
|
|
|
@@ -1050,14 +1155,20 @@ class PocketBaseRecordsCreateCommand extends FlutterPatcherCommand {
|
|
|
1050
1155
|
(c) => c.createRecord<dynamic>(r['collection'] as String, body, (j) => j),
|
|
1051
1156
|
r,
|
|
1052
1157
|
);
|
|
1053
|
-
|
|
1158
|
+
stdout.writeln(
|
|
1159
|
+
' ${dim('→')} record ${cyan((record as Map)['id']?.toString() ?? '?')}',
|
|
1160
|
+
);
|
|
1054
1161
|
});
|
|
1055
1162
|
}
|
|
1056
1163
|
|
|
1057
1164
|
class PocketBaseRecordsUpdateCommand extends FlutterPatcherCommand {
|
|
1058
1165
|
PocketBaseRecordsUpdateCommand() {
|
|
1059
1166
|
_addBackendOptions(argParser);
|
|
1060
|
-
argParser.addOption(
|
|
1167
|
+
argParser.addOption(
|
|
1168
|
+
'collection',
|
|
1169
|
+
help: 'Collection name.',
|
|
1170
|
+
mandatory: true,
|
|
1171
|
+
);
|
|
1061
1172
|
argParser.addOption('id', help: 'Record ID.', mandatory: true);
|
|
1062
1173
|
argParser.addOption('body', help: 'JSON body.', mandatory: true);
|
|
1063
1174
|
}
|
|
@@ -1075,7 +1186,12 @@ class PocketBaseRecordsUpdateCommand extends FlutterPatcherCommand {
|
|
|
1075
1186
|
final body = jsonDecode(r['body'] as String) as Map<String, dynamic>;
|
|
1076
1187
|
await _pbStep(
|
|
1077
1188
|
'Updating ${r['collection']}/${r['id']}',
|
|
1078
|
-
(c) => c.updateRecord<dynamic>(
|
|
1189
|
+
(c) => c.updateRecord<dynamic>(
|
|
1190
|
+
r['collection'] as String,
|
|
1191
|
+
r['id'] as String,
|
|
1192
|
+
body,
|
|
1193
|
+
(j) => j,
|
|
1194
|
+
),
|
|
1079
1195
|
r,
|
|
1080
1196
|
);
|
|
1081
1197
|
step(green('Updated ${r['collection']}/${r['id']}'));
|
|
@@ -1085,7 +1201,11 @@ class PocketBaseRecordsUpdateCommand extends FlutterPatcherCommand {
|
|
|
1085
1201
|
class PocketBaseRecordsDeleteCommand extends FlutterPatcherCommand {
|
|
1086
1202
|
PocketBaseRecordsDeleteCommand() {
|
|
1087
1203
|
_addBackendOptions(argParser);
|
|
1088
|
-
argParser.addOption(
|
|
1204
|
+
argParser.addOption(
|
|
1205
|
+
'collection',
|
|
1206
|
+
help: 'Collection name.',
|
|
1207
|
+
mandatory: true,
|
|
1208
|
+
);
|
|
1089
1209
|
argParser.addOption('id', help: 'Record ID.', mandatory: true);
|
|
1090
1210
|
}
|
|
1091
1211
|
|
|
@@ -1111,19 +1231,25 @@ class PocketBaseRecordsDeleteCommand extends FlutterPatcherCommand {
|
|
|
1111
1231
|
class PocketBaseRecordsBatchCommand extends FlutterPatcherCommand {
|
|
1112
1232
|
PocketBaseRecordsBatchCommand() {
|
|
1113
1233
|
_addBackendOptions(argParser);
|
|
1114
|
-
argParser.addOption(
|
|
1234
|
+
argParser.addOption(
|
|
1235
|
+
'requests',
|
|
1236
|
+
help: 'JSON array of request objects.',
|
|
1237
|
+
mandatory: true,
|
|
1238
|
+
);
|
|
1115
1239
|
}
|
|
1116
1240
|
|
|
1117
1241
|
@override
|
|
1118
1242
|
String get name => 'batch';
|
|
1119
1243
|
|
|
1120
1244
|
@override
|
|
1121
|
-
String get description =>
|
|
1245
|
+
String get description =>
|
|
1246
|
+
'Execute multiple record operations in a single transaction.';
|
|
1122
1247
|
|
|
1123
1248
|
@override
|
|
1124
1249
|
Future<int> run() => runGuarded(() async {
|
|
1125
1250
|
banner('pocketbase · records · batch');
|
|
1126
|
-
final requests =
|
|
1251
|
+
final requests =
|
|
1252
|
+
jsonDecode(argResults!['requests'] as String) as List<dynamic>;
|
|
1127
1253
|
final body = requests.cast<Map<String, dynamic>>();
|
|
1128
1254
|
final results = await _pbStep(
|
|
1129
1255
|
'Executing ${body.length} batch requests',
|
|
@@ -1171,16 +1297,24 @@ class PocketBaseCollectionsListCommand extends FlutterPatcherCommand {
|
|
|
1171
1297
|
@override
|
|
1172
1298
|
Future<int> run() => runGuarded(() async {
|
|
1173
1299
|
banner('pocketbase · collections · list');
|
|
1174
|
-
final cols = await _pbStep(
|
|
1300
|
+
final cols = await _pbStep(
|
|
1301
|
+
'Listing collections',
|
|
1302
|
+
(c) => c.listCollections(),
|
|
1303
|
+
argResults!,
|
|
1304
|
+
);
|
|
1175
1305
|
if (cols.isEmpty) {
|
|
1176
1306
|
warn('No collections found.');
|
|
1177
1307
|
return;
|
|
1178
1308
|
}
|
|
1179
|
-
final rows = cols
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1309
|
+
final rows = cols
|
|
1310
|
+
.map(
|
|
1311
|
+
(c) => [
|
|
1312
|
+
cyan(c['name']?.toString() ?? '?'),
|
|
1313
|
+
c['type']?.toString() ?? '?',
|
|
1314
|
+
'${(c['fields'] as List?)?.length ?? 0} fields',
|
|
1315
|
+
],
|
|
1316
|
+
)
|
|
1317
|
+
.toList();
|
|
1184
1318
|
table('${cols.length} collections', ['NAME', 'TYPE', 'FIELDS'], rows);
|
|
1185
1319
|
});
|
|
1186
1320
|
}
|
|
@@ -1188,7 +1322,11 @@ class PocketBaseCollectionsListCommand extends FlutterPatcherCommand {
|
|
|
1188
1322
|
class PocketBaseCollectionsViewCommand extends FlutterPatcherCommand {
|
|
1189
1323
|
PocketBaseCollectionsViewCommand() {
|
|
1190
1324
|
_addBackendOptions(argParser);
|
|
1191
|
-
argParser.addOption(
|
|
1325
|
+
argParser.addOption(
|
|
1326
|
+
'name',
|
|
1327
|
+
help: 'Collection name or ID.',
|
|
1328
|
+
mandatory: true,
|
|
1329
|
+
);
|
|
1192
1330
|
}
|
|
1193
1331
|
|
|
1194
1332
|
@override
|
|
@@ -1201,7 +1339,11 @@ class PocketBaseCollectionsViewCommand extends FlutterPatcherCommand {
|
|
|
1201
1339
|
Future<int> run() => runGuarded(() async {
|
|
1202
1340
|
banner('pocketbase · collections · view');
|
|
1203
1341
|
final name = argResults!['name'] as String;
|
|
1204
|
-
final col = await _pbStep(
|
|
1342
|
+
final col = await _pbStep(
|
|
1343
|
+
'Viewing $name',
|
|
1344
|
+
(c) => c.getCollection(name),
|
|
1345
|
+
argResults!,
|
|
1346
|
+
);
|
|
1205
1347
|
stdout.writeln(const JsonEncoder.withIndent(' ').convert(col));
|
|
1206
1348
|
});
|
|
1207
1349
|
}
|
|
@@ -1209,7 +1351,11 @@ class PocketBaseCollectionsViewCommand extends FlutterPatcherCommand {
|
|
|
1209
1351
|
class PocketBaseCollectionsCreateCommand extends FlutterPatcherCommand {
|
|
1210
1352
|
PocketBaseCollectionsCreateCommand() {
|
|
1211
1353
|
_addBackendOptions(argParser);
|
|
1212
|
-
argParser.addOption(
|
|
1354
|
+
argParser.addOption(
|
|
1355
|
+
'body',
|
|
1356
|
+
help: 'JSON collection definition.',
|
|
1357
|
+
mandatory: true,
|
|
1358
|
+
);
|
|
1213
1359
|
}
|
|
1214
1360
|
|
|
1215
1361
|
@override
|
|
@@ -1221,9 +1367,13 @@ class PocketBaseCollectionsCreateCommand extends FlutterPatcherCommand {
|
|
|
1221
1367
|
@override
|
|
1222
1368
|
Future<int> run() => runGuarded(() async {
|
|
1223
1369
|
banner('pocketbase · collections · create');
|
|
1224
|
-
final body =
|
|
1225
|
-
|
|
1226
|
-
|
|
1370
|
+
final body =
|
|
1371
|
+
jsonDecode(argResults!['body'] as String) as Map<String, dynamic>;
|
|
1372
|
+
await _pbStep(
|
|
1373
|
+
'Creating ${body['name'] ?? 'collection'}',
|
|
1374
|
+
(c) => c.createCollection(body),
|
|
1375
|
+
argResults!,
|
|
1376
|
+
);
|
|
1227
1377
|
step(green('Created ${body['name'] ?? 'collection'}'));
|
|
1228
1378
|
});
|
|
1229
1379
|
}
|
|
@@ -1231,8 +1381,16 @@ class PocketBaseCollectionsCreateCommand extends FlutterPatcherCommand {
|
|
|
1231
1381
|
class PocketBaseCollectionsUpdateCommand extends FlutterPatcherCommand {
|
|
1232
1382
|
PocketBaseCollectionsUpdateCommand() {
|
|
1233
1383
|
_addBackendOptions(argParser);
|
|
1234
|
-
argParser.addOption(
|
|
1235
|
-
|
|
1384
|
+
argParser.addOption(
|
|
1385
|
+
'name',
|
|
1386
|
+
help: 'Collection name or ID.',
|
|
1387
|
+
mandatory: true,
|
|
1388
|
+
);
|
|
1389
|
+
argParser.addOption(
|
|
1390
|
+
'body',
|
|
1391
|
+
help: 'JSON fields to update.',
|
|
1392
|
+
mandatory: true,
|
|
1393
|
+
);
|
|
1236
1394
|
}
|
|
1237
1395
|
|
|
1238
1396
|
@override
|
|
@@ -1255,7 +1413,11 @@ class PocketBaseCollectionsUpdateCommand extends FlutterPatcherCommand {
|
|
|
1255
1413
|
class PocketBaseCollectionsDeleteCommand extends FlutterPatcherCommand {
|
|
1256
1414
|
PocketBaseCollectionsDeleteCommand() {
|
|
1257
1415
|
_addBackendOptions(argParser);
|
|
1258
|
-
argParser.addOption(
|
|
1416
|
+
argParser.addOption(
|
|
1417
|
+
'name',
|
|
1418
|
+
help: 'Collection name or ID.',
|
|
1419
|
+
mandatory: true,
|
|
1420
|
+
);
|
|
1259
1421
|
}
|
|
1260
1422
|
|
|
1261
1423
|
@override
|
|
@@ -1268,7 +1430,11 @@ class PocketBaseCollectionsDeleteCommand extends FlutterPatcherCommand {
|
|
|
1268
1430
|
Future<int> run() => runGuarded(() async {
|
|
1269
1431
|
banner('pocketbase · collections · delete');
|
|
1270
1432
|
final name = argResults!['name'] as String;
|
|
1271
|
-
await _pbStep(
|
|
1433
|
+
await _pbStep(
|
|
1434
|
+
'Deleting $name',
|
|
1435
|
+
(c) => c.deleteCollection(name),
|
|
1436
|
+
argResults!,
|
|
1437
|
+
);
|
|
1272
1438
|
step(green('Deleted collection $name'));
|
|
1273
1439
|
});
|
|
1274
1440
|
}
|
|
@@ -1276,7 +1442,11 @@ class PocketBaseCollectionsDeleteCommand extends FlutterPatcherCommand {
|
|
|
1276
1442
|
class PocketBaseCollectionsTruncateCommand extends FlutterPatcherCommand {
|
|
1277
1443
|
PocketBaseCollectionsTruncateCommand() {
|
|
1278
1444
|
_addBackendOptions(argParser);
|
|
1279
|
-
argParser.addOption(
|
|
1445
|
+
argParser.addOption(
|
|
1446
|
+
'name',
|
|
1447
|
+
help: 'Collection name or ID.',
|
|
1448
|
+
mandatory: true,
|
|
1449
|
+
);
|
|
1280
1450
|
}
|
|
1281
1451
|
|
|
1282
1452
|
@override
|
|
@@ -1289,7 +1459,11 @@ class PocketBaseCollectionsTruncateCommand extends FlutterPatcherCommand {
|
|
|
1289
1459
|
Future<int> run() => runGuarded(() async {
|
|
1290
1460
|
banner('pocketbase · collections · truncate');
|
|
1291
1461
|
final name = argResults!['name'] as String;
|
|
1292
|
-
await _pbStep(
|
|
1462
|
+
await _pbStep(
|
|
1463
|
+
'Truncating $name',
|
|
1464
|
+
(c) => c.truncateCollection(name),
|
|
1465
|
+
argResults!,
|
|
1466
|
+
);
|
|
1293
1467
|
step(green('Truncated $name'));
|
|
1294
1468
|
});
|
|
1295
1469
|
}
|
|
@@ -1297,8 +1471,16 @@ class PocketBaseCollectionsTruncateCommand extends FlutterPatcherCommand {
|
|
|
1297
1471
|
class PocketBaseCollectionsImportCommand extends FlutterPatcherCommand {
|
|
1298
1472
|
PocketBaseCollectionsImportCommand() {
|
|
1299
1473
|
_addBackendOptions(argParser);
|
|
1300
|
-
argParser.addOption(
|
|
1301
|
-
|
|
1474
|
+
argParser.addOption(
|
|
1475
|
+
'file',
|
|
1476
|
+
help: 'JSON file with collections config.',
|
|
1477
|
+
mandatory: true,
|
|
1478
|
+
);
|
|
1479
|
+
argParser.addFlag(
|
|
1480
|
+
'delete-missing',
|
|
1481
|
+
help: 'Delete collections not in file.',
|
|
1482
|
+
defaultsTo: false,
|
|
1483
|
+
);
|
|
1302
1484
|
}
|
|
1303
1485
|
|
|
1304
1486
|
@override
|
|
@@ -1318,7 +1500,8 @@ class PocketBaseCollectionsImportCommand extends FlutterPatcherCommand {
|
|
|
1318
1500
|
final cols = json.cast<Map<String, dynamic>>();
|
|
1319
1501
|
await _pbStep(
|
|
1320
1502
|
'Importing ${cols.length} collections',
|
|
1321
|
-
(c) =>
|
|
1503
|
+
(c) =>
|
|
1504
|
+
c.importCollections(cols, deleteMissing: r['delete-missing'] as bool),
|
|
1322
1505
|
r,
|
|
1323
1506
|
);
|
|
1324
1507
|
step(green('Imported ${cols.length} collections'));
|
|
@@ -1358,7 +1541,11 @@ class PocketBaseSettingsListCommand extends FlutterPatcherCommand {
|
|
|
1358
1541
|
@override
|
|
1359
1542
|
Future<int> run() => runGuarded(() async {
|
|
1360
1543
|
banner('pocketbase · settings · list');
|
|
1361
|
-
final settings = await _pbStep(
|
|
1544
|
+
final settings = await _pbStep(
|
|
1545
|
+
'Fetching settings',
|
|
1546
|
+
(c) => c.listSettings(),
|
|
1547
|
+
argResults!,
|
|
1548
|
+
);
|
|
1362
1549
|
stdout.writeln(const JsonEncoder.withIndent(' ').convert(settings));
|
|
1363
1550
|
});
|
|
1364
1551
|
}
|
|
@@ -1366,7 +1553,11 @@ class PocketBaseSettingsListCommand extends FlutterPatcherCommand {
|
|
|
1366
1553
|
class PocketBaseSettingsUpdateCommand extends FlutterPatcherCommand {
|
|
1367
1554
|
PocketBaseSettingsUpdateCommand() {
|
|
1368
1555
|
_addBackendOptions(argParser);
|
|
1369
|
-
argParser.addOption(
|
|
1556
|
+
argParser.addOption(
|
|
1557
|
+
'body',
|
|
1558
|
+
help: 'JSON object with settings to update.',
|
|
1559
|
+
mandatory: true,
|
|
1560
|
+
);
|
|
1370
1561
|
}
|
|
1371
1562
|
|
|
1372
1563
|
@override
|
|
@@ -1378,8 +1569,13 @@ class PocketBaseSettingsUpdateCommand extends FlutterPatcherCommand {
|
|
|
1378
1569
|
@override
|
|
1379
1570
|
Future<int> run() => runGuarded(() async {
|
|
1380
1571
|
banner('pocketbase · settings · update');
|
|
1381
|
-
final body =
|
|
1382
|
-
|
|
1572
|
+
final body =
|
|
1573
|
+
jsonDecode(argResults!['body'] as String) as Map<String, dynamic>;
|
|
1574
|
+
await _pbStep(
|
|
1575
|
+
'Updating settings',
|
|
1576
|
+
(c) => c.updateSettings(body),
|
|
1577
|
+
argResults!,
|
|
1578
|
+
);
|
|
1383
1579
|
step(green('Settings updated'));
|
|
1384
1580
|
});
|
|
1385
1581
|
}
|
|
@@ -1387,7 +1583,11 @@ class PocketBaseSettingsUpdateCommand extends FlutterPatcherCommand {
|
|
|
1387
1583
|
class PocketBaseSettingsTestS3Command extends FlutterPatcherCommand {
|
|
1388
1584
|
PocketBaseSettingsTestS3Command() {
|
|
1389
1585
|
_addBackendOptions(argParser);
|
|
1390
|
-
argParser.addOption(
|
|
1586
|
+
argParser.addOption(
|
|
1587
|
+
'filesystem',
|
|
1588
|
+
help: 'Storage filesystem to test.',
|
|
1589
|
+
defaultsTo: 'storage',
|
|
1590
|
+
);
|
|
1391
1591
|
}
|
|
1392
1592
|
|
|
1393
1593
|
@override
|
|
@@ -1443,7 +1643,11 @@ class PocketBaseSettingsTestEmailCommand extends FlutterPatcherCommand {
|
|
|
1443
1643
|
class PocketBaseSqlCommand extends FlutterPatcherCommand {
|
|
1444
1644
|
PocketBaseSqlCommand() {
|
|
1445
1645
|
_addBackendOptions(argParser);
|
|
1446
|
-
argParser.addOption(
|
|
1646
|
+
argParser.addOption(
|
|
1647
|
+
'query',
|
|
1648
|
+
help: 'SQL query to execute.',
|
|
1649
|
+
mandatory: true,
|
|
1650
|
+
);
|
|
1447
1651
|
}
|
|
1448
1652
|
|
|
1449
1653
|
@override
|
|
@@ -1456,8 +1660,13 @@ class PocketBaseSqlCommand extends FlutterPatcherCommand {
|
|
|
1456
1660
|
Future<int> run() => runGuarded(() async {
|
|
1457
1661
|
banner('pocketbase · sql');
|
|
1458
1662
|
final query = argResults!['query'] as String;
|
|
1459
|
-
final result = await _pbStep(
|
|
1460
|
-
|
|
1663
|
+
final result = await _pbStep(
|
|
1664
|
+
'Executing query',
|
|
1665
|
+
(c) => c.runSql(query),
|
|
1666
|
+
argResults!,
|
|
1667
|
+
);
|
|
1668
|
+
final columns = (result['columns'] as List? ?? [])
|
|
1669
|
+
.cast<Map<String, dynamic>>();
|
|
1461
1670
|
final rows = (result['rows'] as List? ?? []).cast<List<dynamic>>();
|
|
1462
1671
|
if (rows.isNotEmpty) {
|
|
1463
1672
|
final colNames = columns.map((c) => '${c['name']}').toList();
|
|
@@ -1500,15 +1709,23 @@ class PocketBaseCronsListCommand extends FlutterPatcherCommand {
|
|
|
1500
1709
|
@override
|
|
1501
1710
|
Future<int> run() => runGuarded(() async {
|
|
1502
1711
|
banner('pocketbase · crons · list');
|
|
1503
|
-
final crons = await _pbStep(
|
|
1712
|
+
final crons = await _pbStep(
|
|
1713
|
+
'Fetching cron jobs',
|
|
1714
|
+
(c) => c.listCrons(),
|
|
1715
|
+
argResults!,
|
|
1716
|
+
);
|
|
1504
1717
|
if (crons.isEmpty) {
|
|
1505
1718
|
warn('No cron jobs registered.');
|
|
1506
1719
|
return;
|
|
1507
1720
|
}
|
|
1508
|
-
final rows = crons
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1721
|
+
final rows = crons
|
|
1722
|
+
.map(
|
|
1723
|
+
(c) => [
|
|
1724
|
+
cyan(c['id']?.toString() ?? '?'),
|
|
1725
|
+
c['expression']?.toString() ?? '?',
|
|
1726
|
+
],
|
|
1727
|
+
)
|
|
1728
|
+
.toList();
|
|
1512
1729
|
table('${crons.length} cron jobs', ['ID', 'EXPRESSION'], rows);
|
|
1513
1730
|
});
|
|
1514
1731
|
}
|
|
@@ -1563,11 +1780,17 @@ class PocketBaseQueryCommand extends FlutterPatcherCommand {
|
|
|
1563
1780
|
if (bodyStr != null && bodyStr.isNotEmpty) {
|
|
1564
1781
|
body = jsonDecode(bodyStr) as Map<String, dynamic>;
|
|
1565
1782
|
}
|
|
1566
|
-
final
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1783
|
+
final (url, admin, pass) = _resolveBackend(r);
|
|
1784
|
+
final client = PocketBaseClient(url);
|
|
1785
|
+
try {
|
|
1786
|
+
await client.authenticate(admin, pass);
|
|
1787
|
+
final res = await client.rawRequest(method, path, body: body);
|
|
1788
|
+
stdout.writeln(
|
|
1789
|
+
const JsonEncoder.withIndent(' ').convert(jsonDecode(res.body)),
|
|
1790
|
+
);
|
|
1791
|
+
} finally {
|
|
1792
|
+
client.close();
|
|
1793
|
+
}
|
|
1571
1794
|
});
|
|
1572
1795
|
}
|
|
1573
1796
|
|
|
@@ -1596,7 +1819,10 @@ class PocketBaseConfigCommand extends FlutterPatcherCommand {
|
|
|
1596
1819
|
kv('url', cyan(url)),
|
|
1597
1820
|
kv('admin', admin),
|
|
1598
1821
|
kv('version', paths.version),
|
|
1599
|
-
kv(
|
|
1822
|
+
kv(
|
|
1823
|
+
'binary',
|
|
1824
|
+
exists ? green(paths.binaryPath.path) : red('not installed'),
|
|
1825
|
+
),
|
|
1600
1826
|
]);
|
|
1601
1827
|
});
|
|
1602
1828
|
}
|