├── .idea ├── .name ├── runConfigurations │ ├── melos_flutter_run_example.xml │ ├── melos_clean.xml │ └── melos_bootstrap.xml └── modules.xml ├── .tool-versions ├── packages ├── example │ ├── .tool-versions │ ├── ios │ │ ├── Flutter │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ └── AppFrameworkInfo.plist │ │ ├── Runner │ │ │ ├── Runner-Bridging-Header.h │ │ │ ├── Assets.xcassets │ │ │ │ ├── LaunchImage.imageset │ │ │ │ │ ├── LaunchImage.png │ │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ │ ├── README.md │ │ │ │ │ └── Contents.json │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ │ └── Contents.json │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj │ │ │ │ ├── Main.storyboard │ │ │ │ └── LaunchScreen.storyboard │ │ │ └── Info.plist │ │ ├── Runner.xcodeproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── RunnerTests │ │ │ └── RunnerTests.swift │ │ └── .gitignore │ ├── android │ │ ├── gradle.properties │ │ ├── app │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ ├── res │ │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── drawable │ │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── values │ │ │ │ │ │ │ └── styles.xml │ │ │ │ │ │ └── values-night │ │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── kotlin │ │ │ │ │ │ └── com │ │ │ │ │ │ │ └── example │ │ │ │ │ │ │ └── example │ │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ ├── debug │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── profile │ │ │ │ │ └── AndroidManifest.xml │ │ │ └── build.gradle │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.properties │ │ ├── .gitignore │ │ ├── build.gradle │ │ └── settings.gradle │ ├── pubspec_overrides.yaml │ ├── CHANGELOG.md │ ├── README.md │ ├── .gitignore │ ├── test │ │ └── widget_test.dart │ ├── .metadata │ ├── analysis_options.yaml │ ├── pubspec.yaml │ └── lib │ │ └── main.dart └── gambit_cli │ ├── .gitignore │ ├── README.md │ ├── bin │ └── gambit_cli.dart │ ├── lib │ ├── src │ │ ├── ios │ │ │ ├── cmd.dart │ │ │ ├── core │ │ │ │ ├── args_consts.dart │ │ │ │ ├── ios_build.dart │ │ │ │ ├── ios_build.g.dart │ │ │ │ ├── provisioning_profile.dart │ │ │ │ ├── provisioning_profile.g.dart │ │ │ │ ├── appstore_connect_utils.dart │ │ │ │ └── ios_build.freezed.dart │ │ │ ├── descriptor.dart │ │ │ ├── use_profile │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ │ ├── testflight_publish │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ │ ├── testflight_last_build_number │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ │ └── get_provisioning_profiles │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ ├── discord │ │ │ ├── cmd.dart │ │ │ ├── descriptor.dart │ │ │ ├── core │ │ │ │ ├── discord_message.dart │ │ │ │ ├── discord_message.g.dart │ │ │ │ ├── discord_embeds.dart │ │ │ │ ├── discord_embeds.g.dart │ │ │ │ └── discord_message.freezed.dart │ │ │ └── notify │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ ├── firebase │ │ │ ├── cmd.dart │ │ │ ├── descriptor.dart │ │ │ ├── last_build_number │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ │ └── app_distribution │ │ │ │ ├── descriptor.dart │ │ │ │ └── cmd.dart │ │ ├── core │ │ │ ├── tasks.extensions.dart │ │ │ ├── exceptions.dart │ │ │ ├── command_descriptor.dart │ │ │ └── gambit_command.dart │ │ └── get_app_version │ │ │ ├── descriptor.dart │ │ │ └── cmd.dart │ └── gambit_cli.dart │ ├── CHANGELOG.md │ ├── pubspec.yaml │ ├── melos_gambit_cli.iml │ └── analysis_options.yaml ├── init_env.sh ├── .gitignore ├── pubspec.yaml ├── melos.yaml ├── doc ├── discord │ ├── discord.md │ └── notify.md ├── get-app-version.md ├── firebase │ ├── firebase.md │ ├── last-build-number.md │ └── distribute.md └── ios │ ├── ios.md │ ├── use-profile.md │ ├── testflight-publish.md │ ├── testflight-last-build-number.md │ └── get-provisioning-profiles.md ├── melos_gambit.iml ├── codemagic.yaml ├── README.md ├── CHANGELOG.md └── pubspec.lock /.idea/.name: -------------------------------------------------------------------------------- 1 | gambit -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | dart 3.4.4 2 | -------------------------------------------------------------------------------- /packages/example/.tool-versions: -------------------------------------------------------------------------------- 1 | flutter 3.22.3-stable 2 | -------------------------------------------------------------------------------- /packages/example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /packages/example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /init_env.sh: -------------------------------------------------------------------------------- 1 | asdf install 2 | dart pub global activate melos 3 | dart pub global activate dcli 4 | melos bs -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/**/* 3 | .packages 4 | build/ 5 | .vscode/ 6 | -------------------------------------------------------------------------------- /packages/example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /packages/gambit_cli/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | ./~/ 5 | ./private_keys/ -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: gambit_monorepo 2 | 3 | environment: 4 | sdk: ">=3.4.4 <4.0.0" 5 | dev_dependencies: 6 | dcli: ^5.0.0 7 | melos: ^6.1.0 8 | -------------------------------------------------------------------------------- /packages/gambit_cli/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /packages/example/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | # melos_managed_dependency_overrides: gambit_cli 2 | dependency_overrides: 3 | gambit_cli: 4 | path: ../gambit_cli 5 | -------------------------------------------------------------------------------- /packages/gambit_cli/bin/gambit_cli.dart: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env dcli 2 | 3 | import 'package:gambit_cli/gambit_cli.dart' as gambit; 4 | 5 | void main(List arguments) => gambit.run(arguments); 6 | -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/cmd.dart: -------------------------------------------------------------------------------- 1 | import '../core/gambit_command.dart'; 2 | import 'descriptor.dart'; 3 | 4 | class IOSCommands extends GambitCommand { 5 | IOSCommands() : super(IOSDescriptor()); 6 | } 7 | -------------------------------------------------------------------------------- /packages/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/cmd.dart: -------------------------------------------------------------------------------- 1 | import '../core/gambit_command.dart'; 2 | import 'descriptor.dart'; 3 | 4 | class DiscordCMD extends GambitCommand { 5 | DiscordCMD():super(DiscordCMDDescriptor()); 6 | } 7 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/firebase/cmd.dart: -------------------------------------------------------------------------------- 1 | import '../core/gambit_command.dart'; 2 | import 'descriptor.dart'; 3 | 4 | class FirebaseCMD extends GambitCommand { 5 | FirebaseCMD() : super(FirebaseDescriptor()); 6 | } 7 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaVilleMonShopping/Gambit-cli/HEAD/packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /melos.yaml: -------------------------------------------------------------------------------- 1 | name: gambit 2 | repository: https://github.com/MaVilleMonShopping/Gambit-cli 3 | 4 | packages: 5 | - packages/** 6 | 7 | version: 8 | message: | 9 | chore: New release ! 10 | {new_packages_versions} 11 | branch: main 12 | -------------------------------------------------------------------------------- /packages/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip 6 | -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/example/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.4 2 | 3 | - **FIX**(testflight-last-build-number): fix parsing error. 4 | 5 | ## 1.0.3 6 | 7 | - Update a dependency to the latest release. 8 | 9 | ## 1.0.2 10 | 11 | - Update a dependency to the latest release. 12 | 13 | ## 1.0.1 14 | 15 | - Update a dependency to the latest release. 16 | 17 | -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations/melos_flutter_run_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /packages/example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /packages/example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/descriptor.dart: -------------------------------------------------------------------------------- 1 | import '../core/command_descriptor.dart'; 2 | import 'notify/cmd.dart'; 3 | 4 | class DiscordCMDDescriptor extends CommandDescriptor { 5 | DiscordCMDDescriptor() 6 | : super( 7 | commandName: "discord", 8 | commandDescription: "discord helper", 9 | subCommands: [DiscordNotifyCMD()], 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /packages/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /packages/example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/core/tasks.extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | 3 | import 'exceptions.dart'; 4 | 5 | typedef GCTaskResult = Either; 6 | 7 | extension BindEither on Task> { 8 | Task> bindRight(Task> Function(R) f) => bind( 9 | (value) => value.fold( 10 | (failure) => Task(() async => Left(failure)), 11 | f, 12 | ), 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/core/exceptions.dart: -------------------------------------------------------------------------------- 1 | class DirectoryNotFound implements Exception { 2 | final String? directoryPath; 3 | DirectoryNotFound({this.directoryPath}); 4 | 5 | @override 6 | String toString() { 7 | return "No directory found at $directoryPath"; 8 | } 9 | } 10 | 11 | class CommandFailure { 12 | final String cause; 13 | final StackTrace? stackTrace; 14 | final int exitCode; 15 | 16 | CommandFailure({required this.cause, this.stackTrace, this.exitCode = 1}); 17 | } 18 | -------------------------------------------------------------------------------- /doc/discord/discord.md: -------------------------------------------------------------------------------- 1 | 2 | # Discord 3 | 4 | Interract with Discord 5 | 6 | ```bash 7 | gambit help discord 8 | ``` 9 | 10 | ```bash 11 | discord helper 12 | 13 | Usage: gambit discord [arguments] 14 | -h, --help Print this usage information. 15 | 16 | Available subcommands: 17 | notify Send message via webhook 18 | 19 | Run "gambit help" to see global options. 20 | ``` 21 | 22 | | command | Description | 23 | |---|---| 24 | | [notify](notify.md) | Upload apk to Firebase App Distribution.| 25 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/firebase/descriptor.dart: -------------------------------------------------------------------------------- 1 | import '../core/command_descriptor.dart'; 2 | import 'app_distribution/cmd.dart'; 3 | import 'last_build_number/cmd.dart'; 4 | 5 | class FirebaseDescriptor extends CommandDescriptor { 6 | FirebaseDescriptor() 7 | : super( 8 | commandName: "firebase", 9 | commandDescription: "All you need for Firebase.", 10 | subCommands: [ 11 | LastBuildNumberCMD(), 12 | AppDistributionCMD(), 13 | ]); 14 | } 15 | -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /doc/get-app-version.md: -------------------------------------------------------------------------------- 1 | # get-app-version 2 | 3 | ```bash 4 | gambit get-app-version -h 5 | ``` 6 | 7 | ```bash 8 | Read flutter app semantic version from pubspec. 9 | 10 | Usage: gambit get-app-version [arguments] 11 | -h, --help Print this usage information. 12 | -f, --folder Path to flutter app root folder, 13 | if not set will try to find flutter pubspec.yaml in current path. 14 | (defaults to current directory) 15 | -v, --verbose Verbose mode, use only for debug 16 | 17 | Run "gambit help" to see global options. 18 | ``` -------------------------------------------------------------------------------- /melos_gambit.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations/melos_clean.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /packages/example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /.idea/runConfigurations/melos_bootstrap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/args_consts.dart: -------------------------------------------------------------------------------- 1 | const String issuerIdArgName = "issuer-id"; 2 | const String apiKeyIdArgName = "api-key-id"; 3 | const String apiPrivateKeyArgName = "api-private-key"; 4 | const String profileTypeArgName = "profile-type"; 5 | const String bundleIdArgName = "bundle-id"; 6 | const String alldArgName = "all"; 7 | const String appIdArgName = "app-id"; 8 | const String preReleaseVersionArgName = "pre-release-version"; 9 | const String outputArgName = "output"; 10 | const String projectPathArgName = "flutter_app_folder"; 11 | const String ipPathArgName = "ipa"; 12 | const String maxTryArgName = "try-upload"; 13 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/gambit_cli.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:args/command_runner.dart'; 4 | import 'src/discord/cmd.dart'; 5 | import 'src/firebase/cmd.dart'; 6 | import 'src/get_app_version/cmd.dart'; 7 | import 'src/ios/cmd.dart'; 8 | 9 | void run(List arguments) { 10 | CommandRunner("gambit", "You helpfull tool for flutter cicd") 11 | ..addCommand( 12 | GetAppVersionCmd(), 13 | ) 14 | ..addCommand(IOSCommands()) 15 | ..addCommand(FirebaseCMD()) 16 | ..addCommand(DiscordCMD()) 17 | ..run(arguments).catchError((error) { 18 | if (error is! UsageException) throw error; 19 | print(error); 20 | exit(64); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/descriptor.dart: -------------------------------------------------------------------------------- 1 | import '../core/command_descriptor.dart'; 2 | import 'get_provisioning_profiles/cmd.dart'; 3 | import 'testflight_last_build_number/cmd.dart'; 4 | import 'testflight_publish/cmd.dart'; 5 | import 'use_profile/cmd.dart'; 6 | 7 | class IOSDescriptor extends CommandDescriptor { 8 | IOSDescriptor() 9 | : super( 10 | commandName: "ios", 11 | commandDescription: """ 12 | All you need for iOS Flutter app. 13 | Only available on MacOS.""", 14 | subCommands: [ 15 | GetProvisioninProfile(), 16 | UseProfile(), 17 | TestflightLastBuildNumberCmd(), 18 | TestflightPublish(), 19 | ], 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /packages/gambit_cli/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.3.3 2 | 3 | - **FIX**(testflight-last-build-number): fix parsing error. 4 | 5 | ## 1.3.2 6 | 7 | - **FIX**(testflight-publish): fix xcrun command error and ipa file path with spaces. 8 | 9 | ## 1.3.1 10 | 11 | - **REFACTOR**(freezed): regen freezed. 12 | - **REFACTOR**: DioError deprecated, use DioException. 13 | - **FIX**(ios): ios testflight-last-build-number fixed response error. 14 | - **FIX**(get-app-version): Fix dans la lecture du pubspec suite bump pubspec_parse. 15 | 16 | ## 1.3.1 17 | 18 | - **REFACTOR**: DioError deprecated, use DioException. 19 | - **FIX**(get-app-version): Fix dans la lecture du pubspec suite bump pubspec_parse. 20 | 21 | ## 1.0.0 22 | 23 | - Initial version. 24 | -------------------------------------------------------------------------------- /doc/firebase/firebase.md: -------------------------------------------------------------------------------- 1 | # Firebase 2 | 3 | All you need for Firebase. 4 | 5 | ```bash 6 | gambit help firebase 7 | ``` 8 | 9 | ```bash 10 | All you need for Firebase. 11 | 12 | Usage: gambit firebase [arguments] 13 | -h, --help Print this usage information. 14 | 15 | Available subcommands: 16 | distribute Upload apk to Firebase App Distribution. 17 | last-build-number Get last build number from App Distribution releases. 18 | 19 | Run "gambit help" to see global options. 20 | ``` 21 | 22 | | command | Description | 23 | |---|---| 24 | | [distribute](distribute.md) | Upload apk to Firebase App Distribution.| 25 | | [last-build-number](last-build-number.md) | Get last build number from App Distribution releases.| 26 | -------------------------------------------------------------------------------- /doc/firebase/last-build-number.md: -------------------------------------------------------------------------------- 1 | # last-build-number 2 | 3 | Get last build number from Testflight. 4 | 5 | ```bash 6 | gambit help firebase last-build-number 7 | ``` 8 | 9 | ```bash 10 | Get last build number from App Distribution releases. 11 | 12 | Usage: gambit firebase last-build-number [arguments] 13 | -h, --help Print this usage information. 14 | -f, --account-service-file (mandatory) Path to your .json service account file. 15 | -p, --project-id (mandatory) Firebase project id. 16 | -a, --app-id (mandatory) Firebase app id. 17 | -n, --default-number If no release found, will return this value. 18 | 19 | Run "gambit help" to see global options. 20 | ``` -------------------------------------------------------------------------------- /packages/example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /packages/gambit_cli/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: gambit_cli 2 | description: A sample command-line application. 3 | version: 1.3.3 4 | publish_to: 'none' 5 | # repository: https://github.com/my_org/my_repo 6 | 7 | environment: 8 | sdk: ^3.4.4 9 | 10 | # Add regular dependencies here. 11 | dependencies: 12 | args: ^2.5.0 13 | dartz: ^0.10.1 14 | dcli: ^5.0.0 15 | dio: ^5.5.0+1 16 | firebaseapis: ^0.2.0 17 | freezed_annotation: ^2.4.4 18 | googleapis_auth: ^1.6.0 19 | jose: ^0.3.4 20 | json_annotation: ^4.9.0 21 | path: ^1.9.0 22 | pubspec_parse: ^1.3.0 23 | yaml: ^3.1.2 24 | # path: ^1.8.0 25 | 26 | dev_dependencies: 27 | build_runner: ^2.4.11 28 | freezed: ^2.5.7 29 | json_serializable: ^6.8.0 30 | lints: ^4.0.0 31 | test: ^1.24.0 32 | -------------------------------------------------------------------------------- /packages/gambit_cli/melos_gambit_cli.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/core/discord_message.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | // ignore: depend_on_referenced_packages 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | 6 | import 'discord_embeds.dart'; 7 | 8 | part 'discord_message.freezed.dart'; 9 | part 'discord_message.g.dart'; 10 | 11 | /// Discord Webhook Payload 12 | /// https://discord.com/developers/docs/resources/webhook#execute-webhook 13 | 14 | @freezed 15 | class DiscordMessage with _$DiscordMessage { 16 | const factory DiscordMessage({ 17 | @Default("") String content, 18 | String? username, 19 | @JsonKey(name: "avatar_url") String? avatarUrl, 20 | bool? tts, 21 | List? embeds, 22 | }) = _DiscordMessage; 23 | factory DiscordMessage.fromJson(Map json) => 24 | _$DiscordMessageFromJson(json); 25 | } 26 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/ios_build.dart: -------------------------------------------------------------------------------- 1 | // ignore: depend_on_referenced_packages 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | 4 | part 'ios_build.freezed.dart'; 5 | part 'ios_build.g.dart'; 6 | 7 | @freezed 8 | class IOSBuild with _$IOSBuild { 9 | const factory IOSBuild({ 10 | required IOSBuildAttributes attributes, 11 | required String id, 12 | required String type, 13 | }) = _IOSBuild; 14 | 15 | factory IOSBuild.fromJson(Map json) => 16 | _$IOSBuildFromJson(json); 17 | } 18 | 19 | @freezed 20 | class IOSBuildAttributes with _$IOSBuildAttributes { 21 | const factory IOSBuildAttributes({ 22 | required String version, 23 | required String processingState, 24 | }) = _IOSBuildAttributes; 25 | 26 | factory IOSBuildAttributes.fromJson(Map json) => 27 | _$IOSBuildAttributesFromJson(json); 28 | } 29 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/use_profile/descriptor.dart: -------------------------------------------------------------------------------- 1 | part of 'cmd.dart'; 2 | 3 | class AppleUseProfileDescriptor extends CommandDescriptor { 4 | AppleUseProfileDescriptor() 5 | : super( 6 | commandName: "use-profile", 7 | commandDescription: """ 8 | Auto select provisioning profile and generate export_options.plist. 9 | Only available on MacOS.""", 10 | options: [ 11 | CommandOption( 12 | name: outputArgName, 13 | abbr: "o", 14 | defaultValue: pwd, 15 | help: "Path folder to save generated export_options.plist.", 16 | ), 17 | CommandOption( 18 | name: projectPathArgName, 19 | abbr: "f", 20 | help: "Path to flutter app root folder.", 21 | defaultValue: pwd, 22 | ), 23 | ], 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /packages/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | -------------------------------------------------------------------------------- /packages/example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/get_app_version/descriptor.dart: -------------------------------------------------------------------------------- 1 | import 'package:dcli/dcli.dart'; 2 | 3 | import '../core/command_descriptor.dart'; 4 | 5 | class GetAppVersionCommandDescriptor extends CommandDescriptor { 6 | static final String projectPathArgName = "folder"; 7 | GetAppVersionCommandDescriptor() 8 | : super( 9 | commandName: "get-app-version", 10 | commandDescription: 11 | "Read flutter app semantic version from pubspec.", 12 | options: [ 13 | CommandOption( 14 | name: projectPathArgName, 15 | abbr: "f", 16 | help: """ 17 | Path to flutter app root folder, 18 | if not set will try to find flutter pubspec.yaml in current path.""", 19 | defaultValue: pwd, 20 | ) 21 | ], 22 | flags: [ 23 | verboseFlag() 24 | ]); 25 | } 26 | -------------------------------------------------------------------------------- /packages/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | } 19 | 20 | plugins { 21 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 22 | id "com.android.application" version "7.3.0" apply false 23 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false 24 | } 25 | 26 | include ":app" 27 | -------------------------------------------------------------------------------- /doc/discord/notify.md: -------------------------------------------------------------------------------- 1 | 2 | # Discord Notify 3 | 4 | Send message via Webhook 5 | 6 | ```bash 7 | gambit help discord notify 8 | ``` 9 | 10 | ```bash 11 | Usage: gambit discord notify [arguments] 12 | -h, --help Print this usage information. 13 | -w, --webhook-url (mandatory) Discord webhook url 14 | -t, --title Embeded Message title 15 | Ignored if a json file is used 16 | -d, --description Embeded Message content 17 | Ignored if a json file is used 18 | -a, --author Embeded Message author 19 | Ignored if a json file is used 20 | -c, --color-hex Embeded Color border (int value), check https://www.spycolor.com/ 21 | Ignored if a json file is used 22 | -f, --file Use a json file rather than the separate arguments. If set, other message parameters are ignored. 23 | 24 | Run "gambit help" to see global options. 25 | ``` -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /packages/example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/core/discord_message.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'discord_message.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$DiscordMessageImpl _$$DiscordMessageImplFromJson(Map json) => 10 | _$DiscordMessageImpl( 11 | content: json['content'] as String? ?? "", 12 | username: json['username'] as String?, 13 | avatarUrl: json['avatar_url'] as String?, 14 | tts: json['tts'] as bool?, 15 | embeds: (json['embeds'] as List?) 16 | ?.map((e) => DiscordMessageEmbed.fromJson(e as Map)) 17 | .toList(), 18 | ); 19 | 20 | Map _$$DiscordMessageImplToJson( 21 | _$DiscordMessageImpl instance) => 22 | { 23 | 'content': instance.content, 24 | 'username': instance.username, 25 | 'avatar_url': instance.avatarUrl, 26 | 'tts': instance.tts, 27 | 'embeds': instance.embeds, 28 | }; 29 | -------------------------------------------------------------------------------- /doc/ios/ios.md: -------------------------------------------------------------------------------- 1 | # IOS 2 | 3 | All you need for iOS Flutter app. 4 | 5 | ```bash 6 | gambit ios -h 7 | ``` 8 | 9 | ```bash 10 | All you need for iOS Flutter app. 11 | Only available on MacOS. 12 | 13 | Usage: gambit ios [arguments] 14 | -h, --help Print this usage information. 15 | 16 | Available subcommands: 17 | get-provisioning-profiles Download provisioning profiles from AppStore Connect. 18 | testflight-last-build-number Get last build number from Testflight. 19 | testflight-publish Validate & Upload ipa to Testflight. 20 | use-profile Auto select provisioning profile and generate export_options.plist. 21 | 22 | Run "gambit help" to see global options. 23 | ``` 24 | 25 | | command | Description | 26 | |---|---| 27 | | [get-provisioning-profiles](get-provisioning-profiles.md) | Download provisioning profiles from AppStore Connect.| 28 | | [use-profile](use-profile.md)| Auto select provisioning profile and generate export_options.plist. | 29 | | [testflight-last-build-number](testflight-last-build-number.md) | Get last build number from Testflight.| 30 | | [testflight-publish](testflight-publish.md) | Validate & Upload ipa to Testflight.| -------------------------------------------------------------------------------- /doc/ios/use-profile.md: -------------------------------------------------------------------------------- 1 | # use-profile 2 | 3 | Only available on MacOS 4 | Auto select provisioning profile and generate export_options.plist. 5 | 6 | ```bash 7 | gambit help ios use-profile 8 | ``` 9 | 10 | ```bash 11 | Auto select provisioning profile and generate export_options.plist. 12 | Only available on MacOS. 13 | 14 | Usage: gambit ios use-profile [arguments] 15 | -h, --help Print this usage information. 16 | -o, --output Path folder to save generated export_options.plist. 17 | (defaults to "/Users/arnauddasilva/Dev/Arnaud DA SILVA/gambit") 18 | -f, --flutter_app_folder Path to flutter app root folder. 19 | (defaults to "/Users/arnauddasilva/Dev/Arnaud DA SILVA/gambit") 20 | 21 | Run "gambit help" to see global options. 22 | ``` 23 | 24 | ## Arguments 25 | 26 | | Argument | abbr | required | default |Description | 27 | |---|---|---| --- |---| 28 | | --output | -o | false | workingDirectory |Path folder to save generated export_options.plist.| 29 | | --flutter_app_folder| -f | false | workingDirectory |Path to flutter app root folder.| 30 | | --verbose | -v | false | | Verbose mode, use only for debug.| -------------------------------------------------------------------------------- /packages/example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /packages/gambit_cli/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | analyzer: 23 | exclude: 24 | - lib/**/*.freezed.dart 25 | - lib/**/*.g.dart 26 | 27 | # For more information about the core and recommended set of lints, see 28 | # https://dart.dev/go/core-lints 29 | 30 | # For additional information about configuring this file, see 31 | # https://dart.dev/guides/language/analysis-options 32 | -------------------------------------------------------------------------------- /packages/example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "7482962148e8d758338d8a28f589f317e1e42ba4" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 17 | base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 18 | - platform: android 19 | create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 20 | base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 21 | - platform: ios 22 | create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 23 | base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 24 | 25 | # User provided section 26 | 27 | # List of Local paths (relative to this file) that should be 28 | # ignored by the migrate tool. 29 | # 30 | # Files that are not part of the templates will be ignored by default. 31 | unmanaged_files: 32 | - 'lib/main.dart' 33 | - 'ios/Runner.xcodeproj/project.pbxproj' 34 | -------------------------------------------------------------------------------- /doc/firebase/distribute.md: -------------------------------------------------------------------------------- 1 | # Distribute 2 | 3 | Upload apk to Firebase App Distribution. 4 | 5 | ```bash 6 | gambit help firebase distribute 7 | ``` 8 | 9 | ```bash 10 | Upload apk to Firebase App Distribution. 11 | 12 | Usage: gambit firebase distribute [arguments] 13 | -h, --help Print this usage information. 14 | -f, --account-service-file (mandatory) Path to your .json service account file. 15 | You need Firebase App Distribution role. 16 | --apk (mandatory) apk path. 17 | --app-id (mandatory) Firebase app id. 18 | --project-id (mandatory) Firebase project id 19 | --testers comma separated list of targeted tester's emails 20 | --test-groups comma separated list of targeted test groups 21 | Example: group1,groupe2,... 22 | -v, --verbose Verbose mode, use only for debug 23 | ``` 24 | 25 | Example: 26 | ```bash 27 | dart bin/gambit.dart firebase distribute \ 28 | -f ${path to service account json file} \ 29 | --apk ${path to apk} \ 30 | --app-id ${direbase app id} \ 31 | --project-id ${firebase project's number} 32 | ``` -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/ios_build.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'ios_build.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$IOSBuildImpl _$$IOSBuildImplFromJson(Map json) => 10 | _$IOSBuildImpl( 11 | attributes: IOSBuildAttributes.fromJson( 12 | json['attributes'] as Map), 13 | id: json['id'] as String, 14 | type: json['type'] as String, 15 | ); 16 | 17 | Map _$$IOSBuildImplToJson(_$IOSBuildImpl instance) => 18 | { 19 | 'attributes': instance.attributes, 20 | 'id': instance.id, 21 | 'type': instance.type, 22 | }; 23 | 24 | _$IOSBuildAttributesImpl _$$IOSBuildAttributesImplFromJson( 25 | Map json) => 26 | _$IOSBuildAttributesImpl( 27 | version: json['version'] as String, 28 | processingState: json['processingState'] as String, 29 | ); 30 | 31 | Map _$$IOSBuildAttributesImplToJson( 32 | _$IOSBuildAttributesImpl instance) => 33 | { 34 | 'version': instance.version, 35 | 'processingState': instance.processingState, 36 | }; 37 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/testflight_publish/descriptor.dart: -------------------------------------------------------------------------------- 1 | part of 'cmd.dart'; 2 | 3 | class TestflightPublishDescriptor extends CommandDescriptor { 4 | TestflightPublishDescriptor() 5 | : super(commandName: "testflight-publish", commandDescription: """ 6 | Validate & Upload ipa to Testflight. 7 | Only available on MacOS.""", options: [ 8 | CommandOption( 9 | name: issuerIdArgName, 10 | help: "Apple AppStore Connect issuer id.", 11 | abbr: "i", 12 | mandatory: true, 13 | ), 14 | CommandOption( 15 | name: apiKeyIdArgName, 16 | abbr: "a", 17 | help: "Apple AppStore Connect key id.", 18 | mandatory: true, 19 | ), 20 | CommandOption( 21 | name: apiPrivateKeyArgName, 22 | abbr: "p", 23 | help: "Apple AppStore Connect private key.", 24 | mandatory: true, 25 | ), 26 | CommandOption( 27 | name: ipPathArgName, 28 | help: "Path to ipa file.", 29 | mandatory: true, 30 | ), 31 | CommandOption( 32 | name: maxTryArgName, 33 | help: "Max upload try", 34 | defaultValue: "1", 35 | ), 36 | ], flags: [ 37 | verboseFlag(), 38 | ]); 39 | } 40 | -------------------------------------------------------------------------------- /doc/ios/testflight-publish.md: -------------------------------------------------------------------------------- 1 | # testflight-publish 2 | 3 | Validate & Upload ipa to Testflight. 4 | 5 | ```bash 6 | gambit help ios testflight-publish 7 | ``` 8 | 9 | ```bash 10 | Validate & Upload ipa to Testflight. 11 | Only available on MacOS. 12 | 13 | Usage: gambit ios testflight-publish [arguments] 14 | -h, --help Print this usage information. 15 | -i, --issuer-id (mandatory) Apple AppStore Connect issuer id. 16 | -a, --api-key-id (mandatory) Apple AppStore Connect key id. 17 | -p, --api-private-key (mandatory) Apple AppStore Connect private key. 18 | --ipa (mandatory) Path to ipa file. 19 | --try-upload Max upload try 20 | (defaults to "1") 21 | -v, --verbose Verbose mode, use only for debug 22 | 23 | Run "gambit help" to see global options. 24 | ``` 25 | 26 | ## Arguments 27 | 28 | | Argument | abbr | required | default |Description | 29 | |---|---|---| --- |---| 30 | | --issuer-id | -i | true | |Apple AppStore Connect issuer id.| 31 | | --api-key-id | -a | true | |Apple AppStore Connect key id. | 32 | | --api-private-key | -p | true | |Apple AppStore Connect private key. **.p8 file content | 33 | | --ipa | | true | | Path to ipa file. | 34 | | --try-upload | | false | 1 | Max upload try| 35 | | --verbose | -v | false | | Verbose mode, use only for debug.| -------------------------------------------------------------------------------- /doc/ios/testflight-last-build-number.md: -------------------------------------------------------------------------------- 1 | # testflight-last-build-number 2 | 3 | Get last build number from Testflight. 4 | 5 | ```bash 6 | gambit help ios testflight-last-build-number 7 | ``` 8 | 9 | ```bash 10 | Get last build number from Testflight. 11 | 12 | Usage: gambit ios testflight-last-build-number [arguments] 13 | -h, --help Print this usage information. 14 | --issuer-id (mandatory) Apple AppStore Connect issuer id. 15 | --api-key-id (mandatory) Apple AppStore Connect key id. 16 | --api-private-key (mandatory) Apple AppStore Connect private key. 17 | --app-id (mandatory) Targeted app id in AppStore. 18 | --pre-release-version Filter on pre-release version (like 1.0.0) 19 | -v, --verbose Verbose mode, use only for debug 20 | 21 | Run "gambit help" to see global options. 22 | ``` 23 | 24 | ## Arguments 25 | 26 | | Argument | abbr | required | default |Description | 27 | |---|---|---| --- |---| 28 | | --issuer-id | -i | true | |Apple AppStore Connect issuer id.| 29 | | --api-key-id | -a | true | |Apple AppStore Connect key id. | 30 | | --api-private-key | -p | true | |Apple AppStore Connect private key. **.p8 file content | 31 | | --app-id | -b | true | | Targeted app id in AppStore. Example: 15849XXXXX | 32 | | --pre-release-version | | false | | Filter on pre-release version (like 1.0.0)| 33 | | --verbose | -v | false | | Verbose mode, use only for debug.| -------------------------------------------------------------------------------- /packages/example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/testflight_last_build_number/descriptor.dart: -------------------------------------------------------------------------------- 1 | import '../../core/command_descriptor.dart'; 2 | import '../core/args_consts.dart'; 3 | 4 | class TestflightLastBuildNumberDescriptor extends CommandDescriptor { 5 | TestflightLastBuildNumberDescriptor() 6 | : super( 7 | commandName: "testflight-last-build-number", 8 | commandDescription: "Get last build number from Testflight.", 9 | options: [ 10 | CommandOption( 11 | name: issuerIdArgName, 12 | help: "Apple AppStore Connect issuer id.", 13 | mandatory: true, 14 | ), 15 | CommandOption( 16 | name: apiKeyIdArgName, 17 | help: "Apple AppStore Connect key id.", 18 | mandatory: true, 19 | ), 20 | CommandOption( 21 | name: apiPrivateKeyArgName, 22 | help: "Apple AppStore Connect private key.", 23 | mandatory: true, 24 | ), 25 | CommandOption( 26 | name: appIdArgName, 27 | help: "Targeted app id in AppStore.", 28 | mandatory: true, 29 | ), 30 | CommandOption( 31 | name: preReleaseVersionArgName, 32 | help: "Filter on pre-release version (like 1.0.0)", 33 | mandatory: false, 34 | ), 35 | ], 36 | flags: [ 37 | verboseFlag() 38 | ]); 39 | } 40 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/provisioning_profile.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | // ignore: depend_on_referenced_packages 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | 6 | part 'provisioning_profile.freezed.dart'; 7 | part 'provisioning_profile.g.dart'; 8 | 9 | @freezed 10 | class AppstoreConnectApiResponse with _$AppstoreConnectApiResponse { 11 | const factory AppstoreConnectApiResponse({ 12 | required List data, 13 | }) = _AppstoreConnectApiResponse; 14 | factory AppstoreConnectApiResponse.fromJson(Map json) => 15 | _$AppstoreConnectApiResponseFromJson(json); 16 | } 17 | 18 | @freezed 19 | class ProvisioningProfile with _$ProvisioningProfile { 20 | const ProvisioningProfile._(); 21 | const factory ProvisioningProfile({ 22 | String? type, 23 | required String id, 24 | required ProvisioningProfileAttributes attributes, 25 | }) = _ProvisioningProfile; 26 | 27 | factory ProvisioningProfile.fromJson(Map json) => 28 | _$ProvisioningProfileFromJson(json); 29 | 30 | String get fileName => "${attributes.uuid}.mobileprovision"; 31 | } 32 | 33 | @freezed 34 | class ProvisioningProfileAttributes with _$ProvisioningProfileAttributes { 35 | const factory ProvisioningProfileAttributes({ 36 | required String profileContent, 37 | required String uuid, 38 | }) = _ProvisioningProfileAttributes; 39 | 40 | factory ProvisioningProfileAttributes.fromJson(Map json) => 41 | _$ProvisioningProfileAttributesFromJson(json); 42 | } 43 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/firebase/last_build_number/descriptor.dart: -------------------------------------------------------------------------------- 1 | part of 'cmd.dart'; 2 | 3 | const String serviceAccountFilePathArgName = "account-service-file"; 4 | const String projectIdArgName = "project-id"; 5 | const String appIdArgName = "app-id"; 6 | const String defaultNumberArgName = "default-number"; 7 | 8 | class _LastBuildNumberDescriptor extends CommandDescriptor { 9 | _LastBuildNumberDescriptor() 10 | : super( 11 | commandName: "last-build-number", 12 | commandDescription: 13 | "Get last build number from App Distribution releases.", 14 | options: [ 15 | CommandOption( 16 | name: serviceAccountFilePathArgName, 17 | abbr: "f", 18 | mandatory: true, 19 | help: "Path to your .json service account file.", 20 | ), 21 | CommandOption( 22 | name: projectIdArgName, 23 | abbr: "p", 24 | mandatory: true, 25 | help: "Firebase project id.", 26 | ), 27 | CommandOption( 28 | name: appIdArgName, 29 | abbr: "a", 30 | mandatory: true, 31 | help: "Firebase app id.", 32 | ), 33 | CommandOption( 34 | name: defaultNumberArgName, 35 | abbr: "n", 36 | mandatory: false, 37 | help: "If no release found, will return this value.", 38 | ), 39 | ], 40 | flags: [ 41 | verboseFlag() 42 | ]); 43 | } 44 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/core/command_descriptor.dart: -------------------------------------------------------------------------------- 1 | import 'gambit_command.dart'; 2 | 3 | class CommandDescriptor { 4 | final String commandName; 5 | final String commandDescription; 6 | final List options; 7 | final List flags; 8 | 9 | final List subCommands; 10 | 11 | CommandDescriptor({ 12 | required this.commandName, 13 | required this.commandDescription, 14 | this.options = const [], 15 | this.flags = const [], 16 | this.subCommands = const [], 17 | }); 18 | } 19 | 20 | class CommandOption { 21 | final String name; 22 | final String? abbr; 23 | final String? help; 24 | final String? defaultValue; 25 | final bool mandatory; 26 | final Iterable? allowed; 27 | final bool hide; 28 | 29 | CommandOption({ 30 | required this.name, 31 | this.abbr, 32 | this.help, 33 | this.defaultValue, 34 | this.mandatory = false, 35 | this.allowed, 36 | this.hide = false, 37 | }); 38 | } 39 | 40 | class CommandFlag { 41 | final String name; 42 | final String? abbr; 43 | final String? help; 44 | final bool negatable; 45 | final bool hide; 46 | final bool? defaultTo; 47 | 48 | const CommandFlag({ 49 | required this.name, 50 | this.abbr, 51 | this.help, 52 | this.negatable = false, 53 | this.hide = false, 54 | this.defaultTo = false, 55 | }); 56 | } 57 | 58 | CommandFlag verboseFlag({bool hide = false, bool? defaultValue}) => CommandFlag( 59 | name: "verbose", 60 | abbr: "v", 61 | help: "Verbose mode, use only for debug", 62 | negatable: false, 63 | hide: hide, 64 | defaultTo: defaultValue, 65 | ); 66 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Example 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | example 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | UIApplicationSupportsIndirectInputEvents 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/provisioning_profile.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'provisioning_profile.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$AppstoreConnectApiResponseImpl _$$AppstoreConnectApiResponseImplFromJson( 10 | Map json) => 11 | _$AppstoreConnectApiResponseImpl( 12 | data: json['data'] as List, 13 | ); 14 | 15 | Map _$$AppstoreConnectApiResponseImplToJson( 16 | _$AppstoreConnectApiResponseImpl instance) => 17 | { 18 | 'data': instance.data, 19 | }; 20 | 21 | _$ProvisioningProfileImpl _$$ProvisioningProfileImplFromJson( 22 | Map json) => 23 | _$ProvisioningProfileImpl( 24 | type: json['type'] as String?, 25 | id: json['id'] as String, 26 | attributes: ProvisioningProfileAttributes.fromJson( 27 | json['attributes'] as Map), 28 | ); 29 | 30 | Map _$$ProvisioningProfileImplToJson( 31 | _$ProvisioningProfileImpl instance) => 32 | { 33 | 'type': instance.type, 34 | 'id': instance.id, 35 | 'attributes': instance.attributes, 36 | }; 37 | 38 | _$ProvisioningProfileAttributesImpl 39 | _$$ProvisioningProfileAttributesImplFromJson(Map json) => 40 | _$ProvisioningProfileAttributesImpl( 41 | profileContent: json['profileContent'] as String, 42 | uuid: json['uuid'] as String, 43 | ); 44 | 45 | Map _$$ProvisioningProfileAttributesImplToJson( 46 | _$ProvisioningProfileAttributesImpl instance) => 47 | { 48 | 'profileContent': instance.profileContent, 49 | 'uuid': instance.uuid, 50 | }; 51 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/use_profile/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:dcli/dcli.dart'; 3 | import 'package:path/path.dart'; 4 | import '../../core/command_descriptor.dart'; 5 | import '../../core/gambit_command.dart'; 6 | import '../core/args_consts.dart'; 7 | part 'descriptor.dart'; 8 | 9 | class UseProfile extends GambitCommand { 10 | UseProfile() : super(AppleUseProfileDescriptor()) { 11 | verboseEnabled = true; 12 | } 13 | 14 | @override 15 | void run() { 16 | if (!Platform.isMacOS) { 17 | printError( 18 | "Only avalaible on MacOS, your are running gambit on ${Platform.operatingSystem}"); 19 | exit(1); 20 | } 21 | printDebug("Generating ${argResults![outputArgName]}"); 22 | 23 | Directory output = Directory(argResults![outputArgName]); 24 | 25 | printDebug(blue("Output set to ${output.absolute.path}")); 26 | String xcodeprojPath; 27 | try { 28 | printDebug(blue( 29 | "Searching xcodeproj recursively in ${argResults![projectPathArgName]}")); 30 | 31 | xcodeprojPath = find( 32 | '*.xcodeproj', 33 | workingDirectory: "${argResults![projectPathArgName]}", 34 | recursive: true, 35 | types: [Find.directory, Find.file], 36 | caseSensitive: false, 37 | ).toList().first; 38 | printDebug(green("Found: $xcodeprojPath")); 39 | } catch (ex) { 40 | printError(ex.toString()); 41 | printError("*.xcodeproj not found"); 42 | exit(1); 43 | } 44 | 45 | if (!output.existsSync()) { 46 | output.createSync(recursive: true); 47 | } 48 | 49 | String xcodeCommand = "xcode-project use-profiles"; 50 | xcodeCommand += 51 | ' --export-options-plist "${join(argResults![outputArgName], "export_options.plist")}"'; 52 | xcodeCommand += 53 | ' --project "${join(argResults![projectPathArgName], "**/*.xcodeproj")}"'; 54 | xcodeCommand.run; 55 | exit(0); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/firebase/app_distribution/descriptor.dart: -------------------------------------------------------------------------------- 1 | part of 'cmd.dart'; 2 | 3 | const String serviceAccountFilePathArgName = "account-service-file"; 4 | const String projectIdArgName = "project-id"; 5 | const String appIdArgName = "app-id"; 6 | const String apkPathArgName = "apk"; 7 | const String testersArgName = "testers"; 8 | const String testGroupsArgName = "test-groups"; 9 | 10 | class _AppDistributionDescriptor extends CommandDescriptor { 11 | _AppDistributionDescriptor() 12 | : super( 13 | commandName: "distribute", 14 | commandDescription: "Upload apk to Firebase App Distribution.", 15 | options: [ 16 | CommandOption( 17 | name: serviceAccountFilePathArgName, 18 | abbr: "f", 19 | mandatory: true, 20 | help: 21 | "Path to your .json service account file.\nYou need Firebase App Distribution role.", 22 | ), 23 | CommandOption( 24 | name: apkPathArgName, 25 | mandatory: true, 26 | help: "apk path.", 27 | ), 28 | CommandOption( 29 | name: appIdArgName, 30 | mandatory: true, 31 | help: "Firebase app id.", 32 | ), 33 | CommandOption( 34 | name: projectIdArgName, 35 | mandatory: true, 36 | help: "Firebase project id", 37 | ), 38 | CommandOption( 39 | name: testersArgName, 40 | help: "comma separated list of targeted tester's emails", 41 | ), 42 | CommandOption( 43 | name: testGroupsArgName, 44 | help: 45 | "comma separated list of targeted test groups\nExample: group1,group2,...", 46 | ), 47 | ], 48 | flags: [ 49 | verboseFlag(), 50 | ]); 51 | } 52 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/core/gambit_command.dart: -------------------------------------------------------------------------------- 1 | import 'package:args/command_runner.dart'; 2 | import 'package:dcli/dcli.dart'; 3 | 4 | import 'command_descriptor.dart'; 5 | 6 | abstract class GambitCommand extends Command { 7 | final CommandDescriptor commandDescriptor; 8 | bool verboseEnabled = false; 9 | 10 | @override 11 | String get description => commandDescriptor.commandDescription; 12 | 13 | @override 14 | String get name => commandDescriptor.commandName; 15 | 16 | GambitCommand(this.commandDescriptor) { 17 | for (final option in commandDescriptor.options) { 18 | argParser.addOption( 19 | option.name, 20 | abbr: option.abbr, 21 | help: option.help, 22 | defaultsTo: option.defaultValue, 23 | mandatory: option.mandatory, 24 | allowed: option.allowed, 25 | hide: option.hide, 26 | ); 27 | } 28 | 29 | for (final flag in commandDescriptor.flags) { 30 | argParser.addFlag( 31 | flag.name, 32 | abbr: flag.abbr, 33 | help: flag.help, 34 | negatable: flag.negatable, 35 | defaultsTo: flag.defaultTo, 36 | hide: flag.hide, 37 | ); 38 | } 39 | 40 | for (final sub in commandDescriptor.subCommands) { 41 | addSubcommand(sub); 42 | } 43 | } 44 | 45 | printDebug( 46 | String message, { 47 | String verbosePrefix = "", 48 | String verboseSuffix = "", 49 | }) { 50 | if (verboseEnabled) { 51 | print("$verbosePrefix $message $verboseSuffix".trim()); 52 | } 53 | } 54 | 55 | printSuccess( 56 | String message, { 57 | String verbosePrefix = "", 58 | String verboseSuffix = "", 59 | }) { 60 | if (verboseEnabled) { 61 | print(green("$verbosePrefix $message $verboseSuffix".trim())); 62 | } else { 63 | print(message); 64 | } 65 | } 66 | 67 | printError(String message) { 68 | printerr(red(message)); 69 | } 70 | 71 | void checkVerboseMode() { 72 | verboseEnabled = argResults!["verbose"] ?? false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /doc/ios/get-provisioning-profiles.md: -------------------------------------------------------------------------------- 1 | # get-provisioning-profiles 2 | 3 | Only available on MacOS 4 | 5 | ```bash 6 | gambit help ios get-provisioning-profiles 7 | ``` 8 | 9 | ```bash 10 | Download provisioning profiles from AppStore Connect. 11 | Only available on MacOS. 12 | 13 | Usage: gambit ios get-provisioning-profiles [arguments] 14 | -h, --help Print this usage information. 15 | -i, --issuer-id (mandatory) Apple AppStore Connect issuer id. 16 | -o, --output (defaults to "~/Library/MobileDevice/Provisioning Profiles") 17 | -a, --api-key-id (mandatory) Apple AppStore Connect key id. 18 | -p, --api-private-key (mandatory) Apple AppStore Connect private key. 19 | -b, --bundle-id Application bundle id (com.example.app) 20 | Ignored if --all. 21 | -t, --profile-type Provisioning profile type. 22 | [IOS_APP_STORE (default), IOS_APP_DEVELOPMENT, IOS_APP_ADHOC, IOS_APP_INHOUSE, MAC_APP_DEVELOPMENT, MAC_APP_STORE, MAC_APP_DIRECT, TVOS_APP_DEVELOPMENT, TVOS_APP_STORE, TVOS_APP_ADHOC, TVOS_APP_INHOUSE, MAC_CATALYST_APP_DEVELOPMENT, MAC_CATALYST_APP_STORE, MAC_CATALYST_APP_DIRECT] 23 | --all Download all profiles from AppStore Connect. 24 | Override bundle-id option. 25 | 26 | Run "gambit help" to see global options. 27 | ``` 28 | 29 | ## Arguments 30 | 31 | | Argument | abbr | required | default |Description | 32 | |---|---|---| --- |---| 33 | | --issuer-id | -i | true | |Apple AppStore Connect issuer id.| 34 | | --api-key-id | -a | true | |Apple AppStore Connect key id. | 35 | | --api-private-key | -p | true | |Apple AppStore Connect private key. **.p8 file content | 36 | | --bundle-id | -b | false if --all used | | Application bundle id (com.example.app) | 37 | | --all | | false if --bundle-id used | | Download all profiles from AppStore Connect.| 38 | | --output | -o | false | ~/Library/MobileDevice/Provisioning Profiles | Folder where to save profiles | 39 | | --verbose | -v | false | | Verbose mode, use only for debug.| -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/notify/descriptor.dart: -------------------------------------------------------------------------------- 1 | import '../../core/command_descriptor.dart'; 2 | 3 | const String webhookUrlArgName = "webhook-url"; 4 | const String titleArgName = "title"; 5 | const String descriptionArgName = "description"; 6 | const String authorArgName = "author"; 7 | const String colorArgName = "color-hex"; 8 | const String fileArgName = "file"; 9 | 10 | class DiscordNotifyDescriptor extends CommandDescriptor { 11 | DiscordNotifyDescriptor() 12 | : super( 13 | commandName: "notify", 14 | commandDescription: "Send message via webhook", 15 | options: [ 16 | CommandOption( 17 | name: webhookUrlArgName, 18 | abbr: "w", 19 | help: "Discord webhook url", 20 | mandatory: true, 21 | ), 22 | CommandOption( 23 | name: titleArgName, 24 | abbr: "t", 25 | help: """Embeded Message title 26 | Ignored if a json file is used""", 27 | mandatory: false, 28 | ), 29 | CommandOption( 30 | name: descriptionArgName, 31 | abbr: "d", 32 | help: """Embeded Message content 33 | Ignored if a json file is used""", 34 | mandatory: false, 35 | ), 36 | CommandOption( 37 | name: authorArgName, 38 | abbr: "a", 39 | help: """Embeded Message author 40 | Ignored if a json file is used""", 41 | mandatory: false, 42 | ), 43 | CommandOption( 44 | name: colorArgName, 45 | abbr: "c", 46 | help: 47 | """Embeded Color border (int value), check https://www.spycolor.com/ 48 | Ignored if a json file is used""", 49 | mandatory: false, 50 | ), 51 | CommandOption( 52 | name: fileArgName, 53 | abbr: "f", 54 | help: 55 | "Use a json file rather than the separate arguments. If set, other message parameters are ignored.", 56 | ) 57 | ], 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /packages/example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace "com.example.example" 27 | compileSdk flutter.compileSdkVersion 28 | ndkVersion flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 45 | applicationId "com.example.example" 46 | // You can update the following values to match your application needs. 47 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 48 | minSdkVersion flutter.minSdkVersion 49 | targetSdkVersion flutter.targetSdkVersion 50 | versionCode flutterVersionCode.toInteger() 51 | versionName flutterVersionName 52 | } 53 | 54 | buildTypes { 55 | release { 56 | // TODO: Add your own signing config for the release build. 57 | // Signing with the debug keys for now, so `flutter run --release` works. 58 | signingConfig signingConfigs.debug 59 | } 60 | } 61 | } 62 | 63 | flutter { 64 | source '../..' 65 | } 66 | 67 | dependencies {} 68 | -------------------------------------------------------------------------------- /packages/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/notify/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:dartz/dartz.dart'; 5 | import 'package:dio/dio.dart'; 6 | 7 | import '../../core/exceptions.dart'; 8 | import '../../core/gambit_command.dart'; 9 | import '../../core/tasks.extensions.dart'; 10 | import '../core/discord_embeds.dart'; 11 | import '../core/discord_message.dart'; 12 | import 'descriptor.dart'; 13 | 14 | class DiscordNotifyCMD extends GambitCommand { 15 | late String webhookUrl; 16 | late DiscordMessage message; 17 | DiscordNotifyCMD() : super(DiscordNotifyDescriptor()); 18 | 19 | @override 20 | run() async { 21 | final runResult = await _parseArgs().bindRight(_executeWebhook).run(); 22 | 23 | runResult.fold((fail) { 24 | printError(fail.cause); 25 | exit(fail.exitCode); 26 | }, (success) { 27 | exit(0); 28 | }); 29 | } 30 | 31 | Task> _parseArgs() => 32 | Task>(() async { 33 | if (argResults![fileArgName] != null) { 34 | _createMessageFromJsonFile(); 35 | } else { 36 | _createMessageFromSplittedArgs(); 37 | } 38 | webhookUrl = argResults![webhookUrlArgName]; 39 | return right(unit); 40 | }); 41 | 42 | void _createMessageFromJsonFile() { 43 | final jsonFromFile = 44 | jsonDecode(File(argResults![fileArgName]).readAsStringSync()); 45 | message = DiscordMessage.fromJson(jsonFromFile); 46 | } 47 | 48 | void _createMessageFromSplittedArgs() { 49 | message = DiscordMessage(embeds: [ 50 | DiscordMessageEmbed.withAuthorName( 51 | title: argResults![titleArgName], 52 | description: argResults![descriptionArgName], 53 | author: argResults![authorArgName], 54 | color: int.tryParse(argResults![colorArgName]), 55 | ), 56 | ]); 57 | } 58 | 59 | Task> _executeWebhook(_) => 60 | Task>(() async { 61 | final dioOptions = BaseOptions(baseUrl: webhookUrl); 62 | final dio = Dio(dioOptions); 63 | try { 64 | await dio.post("", data: message.toJson()); 65 | return right("Message sent !"); 66 | } on DioException catch (err) { 67 | return left(CommandFailure(cause: err.message ?? err.toString())); 68 | } 69 | }); 70 | } 71 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/get_provisioning_profiles/descriptor.dart: -------------------------------------------------------------------------------- 1 | part of 'cmd.dart'; 2 | 3 | class _GetProvisoningProfileDescriptor extends CommandDescriptor { 4 | _GetProvisoningProfileDescriptor() 5 | : super(commandName: "get-provisioning-profiles", commandDescription: """ 6 | Download provisioning profiles from AppStore Connect. 7 | Only available on MacOS.""", options: [ 8 | CommandOption( 9 | name: issuerIdArgName, 10 | help: "Apple AppStore Connect issuer id.", 11 | abbr: "i", 12 | mandatory: true, 13 | ), 14 | CommandOption( 15 | name: outputArgName, 16 | abbr: "o", 17 | mandatory: false, 18 | defaultValue: 19 | "${Platform.environment['HOME']}/Library/MobileDevice/Provisioning Profiles", 20 | ), 21 | CommandOption( 22 | name: apiKeyIdArgName, 23 | abbr: "a", 24 | help: "Apple AppStore Connect key id.", 25 | mandatory: true, 26 | ), 27 | CommandOption( 28 | name: apiPrivateKeyArgName, 29 | abbr: "p", 30 | help: "Apple AppStore Connect private key.", 31 | mandatory: true, 32 | ), 33 | CommandOption( 34 | name: bundleIdArgName, 35 | abbr: "b", 36 | help: """ 37 | Application bundle id (com.example.app) 38 | Ignored if --all.""", 39 | ), 40 | CommandOption( 41 | name: profileTypeArgName, 42 | abbr: "t", 43 | allowed: [ 44 | "IOS_APP_STORE", 45 | "IOS_APP_DEVELOPMENT", 46 | "IOS_APP_ADHOC", 47 | "IOS_APP_INHOUSE", 48 | "MAC_APP_DEVELOPMENT", 49 | "MAC_APP_STORE", 50 | "MAC_APP_DIRECT", 51 | "TVOS_APP_DEVELOPMENT", 52 | "TVOS_APP_STORE", 53 | "TVOS_APP_ADHOC", 54 | "TVOS_APP_INHOUSE", 55 | "MAC_CATALYST_APP_DEVELOPMENT", 56 | "MAC_CATALYST_APP_STORE", 57 | "MAC_CATALYST_APP_DIRECT" 58 | ], 59 | help: "Provisioning profile type.", 60 | mandatory: false, 61 | defaultValue: "IOS_APP_STORE") 62 | ], flags: [ 63 | CommandFlag( 64 | name: alldArgName, 65 | help: """ 66 | Download all profiles from AppStore Connect. 67 | Override $bundleIdArgName option.""", 68 | ) 69 | ]); 70 | } 71 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/testflight_last_build_number/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | 5 | import '../../core/exceptions.dart'; 6 | import '../../core/gambit_command.dart'; 7 | import '../../core/tasks.extensions.dart'; 8 | import '../core/appstore_connect_utils.dart'; 9 | import '../core/args_consts.dart'; 10 | import 'descriptor.dart'; 11 | 12 | class TestflightLastBuildNumberCmd extends GambitCommand { 13 | late String apiPrivateKey; 14 | late String apiKeyId; 15 | late String issuerId; 16 | late String appId; 17 | late String? preReleaseVersion; 18 | 19 | late AppStoreConnectClient _appStoreConnectClient; 20 | TestflightLastBuildNumberCmd() 21 | : super( 22 | TestflightLastBuildNumberDescriptor(), 23 | ); 24 | 25 | @override 26 | void run() async { 27 | (await _initialize().bindRight(_getTestflightLastVersion).run()).fold( 28 | (fail) { 29 | printError(fail.cause); 30 | exit(fail.exitCode); 31 | }, 32 | (lastVersion) { 33 | printSuccess(lastVersion, verbosePrefix: "Last build version:"); 34 | exit(0); 35 | }, 36 | ); 37 | } 38 | 39 | Task> _initialize() => Task>(() async { 40 | if (!Platform.isMacOS) { 41 | return left(CommandFailure( 42 | cause: 43 | "Only avalaible on MacOS, your are running gambit on ${Platform.operatingSystem}")); 44 | } 45 | checkVerboseMode(); 46 | apiPrivateKey = argResults![apiPrivateKeyArgName]; 47 | apiKeyId = argResults![apiKeyIdArgName]; 48 | issuerId = argResults![issuerIdArgName]; 49 | appId = argResults![appIdArgName]; 50 | preReleaseVersion = argResults![preReleaseVersionArgName]; 51 | 52 | _appStoreConnectClient = AppStoreConnectClient( 53 | apiPrivateKey: apiPrivateKey, 54 | apiKeyId: apiKeyId, 55 | issuerId: issuerId, 56 | ); 57 | return right(unit); 58 | }); 59 | 60 | Task> _getTestflightLastVersion(_) => 61 | Task>(() async { 62 | try { 63 | final lastVersion = 64 | await _appStoreConnectClient.getLastTestflightBuildNumber( 65 | appId: appId, 66 | preReleaseVersion: preReleaseVersion, 67 | ); 68 | return right(lastVersion); 69 | } catch (ex) { 70 | return left( 71 | CommandFailure( 72 | cause: "Can't find build for $appId $preReleaseVersion: $ex", 73 | ), 74 | ); 75 | } 76 | }); 77 | } 78 | -------------------------------------------------------------------------------- /codemagic.yaml: -------------------------------------------------------------------------------- 1 | definitions: 2 | env_versions: &env_versions 3 | flutter: 3.22.3 4 | groups: 5 | - mvms 6 | triggering_options: &triggering_options 7 | events: 8 | - tag 9 | tag_patterns: # Include or exclude watched tag labels 10 | - pattern: 'gambit_cli-v*' 11 | include: true 12 | 13 | workflows: 14 | compile-mac: 15 | instance_type: mac_mini_m1 16 | environment: 17 | <<: *env_versions 18 | triggering: 19 | <<: *triggering_options 20 | 21 | scripts: 22 | - name: Install dependencies 23 | script: dart pub get 24 | 25 | - name: Create target Dir 26 | script: mkdir macos 27 | 28 | - &install_env 29 | name: install env 30 | script: | 31 | dart pub global activate melos 32 | dart pub global activate dcli 33 | melos bs 34 | 35 | - name: Compile 36 | script: dart compile exe ./packages/gambit_cli/bin/gambit_cli.dart -o macos/gambit 37 | 38 | artifacts: 39 | - macos 40 | 41 | publishing: 42 | scripts: 43 | - name: Publish to github 44 | script: | 45 | set -x 46 | 47 | tar -zcvf macos.tar.gz macos 48 | release=$(gh release view ${CM_TAG}) 49 | echo "$release" 50 | if [ -z "$release" ]; then 51 | gh release create "${CM_TAG}" \ 52 | --title "${CM_TAG}" \ 53 | macos.tar.gz 54 | else 55 | gh release upload "${CM_TAG}" \ 56 | macos.tar.gz 57 | fi 58 | 59 | compile-linux: 60 | instance_type: linux_x2 61 | 62 | environment: 63 | <<: *env_versions 64 | triggering: 65 | <<: *triggering_options 66 | 67 | scripts: 68 | - name: Install dependencies 69 | script: dart pub get 70 | 71 | - name: Create target Dir 72 | script: mkdir linux 73 | 74 | - *install_env 75 | 76 | - name: Compile 77 | script: dart compile exe ./packages/gambit_cli/bin/gambit_cli.dart -o linux/gambit 78 | 79 | artifacts: 80 | - linux 81 | 82 | publishing: 83 | scripts: 84 | - name: Publish to github 85 | script: | 86 | set -x 87 | tar -zcvf linux.tar.gz linux 88 | 89 | release=$(gh release view ${CM_TAG}) 90 | echo "$release" 91 | if [ -z "$release" ]; then 92 | gh release create "${CM_TAG}" \ 93 | --title "${CM_TAG}" \ 94 | linux.tar.gz 95 | else 96 | gh release upload "${CM_TAG}" \ 97 | linux.tar.gz 98 | fi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gambit-cli 2 | [![melos](https://img.shields.io/badge/maintained%20with-melos-f700ff.svg?style=flat-square)](https://github.com/invertase/melos) 3 | 4 | 5 | Your usefull cli tool for flutter cicd automation. 6 | Written in Dart. 7 | 8 | Inspired by [Codemagic cli tools](https://github.com/codemagic-ci-cd/cli-tools) && [Fastlane](https://fastlane.tools/) 9 | 10 | Gambit-cli can be used on Linux & MacOS. 11 | 12 | Some features refering ios builds are disabled on Linux. 13 | 14 | # Install 15 | 16 | WIP 17 | ```sh 18 | ``` 19 | 20 | ## CLI Usage 21 | 22 | ```bash 23 | You helpfull tool for flutter cicd 24 | 25 | Usage: gambit [arguments] 26 | 27 | Global options: 28 | -h, --help Print this usage information. 29 | 30 | Available commands: 31 | discord discord helper 32 | firebase All you need for Firebase. 33 | get-app-version Read flutter app semantic version from pubspec. 34 | ios All you need for iOS Flutter app. 35 | 36 | Run "gambit help " for more information about a command. 37 | ``` 38 | 39 | | command | Description | 40 | |---|---| 41 | | help | Show help | 42 | | [discord](doc/discord/discord.md) | Interract with Discord 43 | | [firebase](doc/firebase/firebase.md) | All you need for Firebase. | 44 | | [get-app-version](doc/get-app-version.md) | Read flutter app semantic version from pubspec. | 45 | | [iOS](doc/ios/ios.md) | iOS related commands. | 46 | 47 | 48 | 49 | 50 | ## Contributors ✨ 51 | 52 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |

Danaru

📖 💻

BERNARD Ghislain

💻 👀
63 | 64 | 65 | 66 | 67 | 68 | 69 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 70 | ======= 71 | -------------------------------------------------------------------------------- /packages/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/core/discord_embeds.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | // ignore: depend_on_referenced_packages 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | 6 | part 'discord_embeds.freezed.dart'; 7 | part 'discord_embeds.g.dart'; 8 | 9 | @freezed 10 | class DiscordMessageEmbed with _$DiscordMessageEmbed { 11 | const factory DiscordMessageEmbed({ 12 | String? title, 13 | String? type, 14 | String? description, 15 | String? url, 16 | int? timestamp, 17 | int? color, 18 | EmbededFooter? footer, 19 | EmbededMedia? image, 20 | EmbededMedia? thumbnail, 21 | EmbededMedia? video, 22 | EmbededProvider? provider, 23 | EmbededAuthor? author, 24 | List? fields, 25 | }) = _DiscordMessageEmbed; 26 | 27 | factory DiscordMessageEmbed.withAuthorName({ 28 | String type = "rich", 29 | required String title, 30 | String description = "", 31 | String? author, 32 | int? color, 33 | }) => 34 | DiscordMessageEmbed( 35 | title: title, 36 | type: type, 37 | description: description, 38 | author: author != null ? EmbededAuthor(name: author) : null, 39 | color: color, 40 | ); 41 | 42 | factory DiscordMessageEmbed.fromJson(Map json) => 43 | _$DiscordMessageEmbedFromJson(json); 44 | } 45 | 46 | @freezed 47 | class EmbededFooter with _$EmbededFooter { 48 | const factory EmbededFooter({ 49 | required String text, 50 | @JsonKey(name: "icon_url") String? iconUrl, 51 | @JsonKey(name: "proxy_icon_url") String? proxyIconUrl, 52 | }) = _EmbededFooter; 53 | 54 | factory EmbededFooter.fromJson(Map json) => 55 | _$EmbededFooterFromJson(json); 56 | } 57 | 58 | @freezed 59 | class EmbededMedia with _$EmbededMedia { 60 | const factory EmbededMedia({ 61 | required String url, 62 | @JsonKey(name: "proxy_url") String? proxyUl, 63 | int? height, 64 | int? width, 65 | }) = _EmbededMedia; 66 | 67 | factory EmbededMedia.fromJson(Map json) => 68 | _$EmbededMediaFromJson(json); 69 | } 70 | 71 | @freezed 72 | class EmbededProvider with _$EmbededProvider { 73 | const factory EmbededProvider({ 74 | String? name, 75 | String? url, 76 | }) = _EmbededProvider; 77 | 78 | factory EmbededProvider.fromJson(Map json) => 79 | _$EmbededProviderFromJson(json); 80 | } 81 | 82 | @freezed 83 | class EmbededAuthor with _$EmbededAuthor { 84 | const factory EmbededAuthor({ 85 | required String name, 86 | String? url, 87 | @JsonKey(name: "icon_url") String? iconUrl, 88 | @JsonKey(name: "proxy_icon_url") String? proxyIconUrl, 89 | }) = _EmbededAuthor; 90 | 91 | factory EmbededAuthor.fromJson(Map json) => 92 | _$EmbededAuthorFromJson(json); 93 | } 94 | 95 | @freezed 96 | class EmbededField with _$EmbededField { 97 | const factory EmbededField({ 98 | required String name, 99 | required String value, 100 | bool? inline, 101 | }) = _EmbededField; 102 | 103 | factory EmbededField.fromJson(Map json) => 104 | _$EmbededFieldFromJson(json); 105 | } 106 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/get_app_version/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:dartz/dartz.dart'; 3 | import 'package:dcli/dcli.dart'; 4 | import 'package:pubspec_parse/pubspec_parse.dart'; 5 | 6 | import '../core/exceptions.dart'; 7 | import '../core/gambit_command.dart'; 8 | import '../core/tasks.extensions.dart'; 9 | import 'descriptor.dart'; 10 | 11 | class GetAppVersionCmd extends GambitCommand { 12 | late String flutterProjectPath; 13 | 14 | GetAppVersionCmd() : super(GetAppVersionCommandDescriptor()); 15 | 16 | @override 17 | run() async { 18 | flutterProjectPath = 19 | argResults![GetAppVersionCommandDescriptor.projectPathArgName]; 20 | 21 | final runResult = await _checkFlutterFolder() 22 | .bindRight(_getFlutterPubspec) 23 | .bindRight(_getSemanticVersion) 24 | .run(); 25 | 26 | runResult.fold( 27 | (failure) { 28 | printError(failure.cause); 29 | exit(failure.exitCode); 30 | }, 31 | (semanticVersion) { 32 | printSuccess(semanticVersion, verbosePrefix: "Version:"); 33 | exit(0); 34 | }, 35 | ); 36 | } 37 | 38 | Task> _checkFlutterFolder() => 39 | Task>(() async { 40 | final currentDirectory = Directory(flutterProjectPath); 41 | if (!currentDirectory.existsSync()) { 42 | return left( 43 | CommandFailure( 44 | cause: "No directory found at ${currentDirectory.absolute.path}", 45 | exitCode: 1, 46 | ), 47 | ); 48 | } 49 | return right(currentDirectory); 50 | }); 51 | 52 | Task> _getFlutterPubspec( 53 | Directory flutterProjectDirectory) => 54 | Task>(() async { 55 | printDebug(yellow( 56 | 'Seaching pubspec into: ${flutterProjectDirectory.absolute.path}')); 57 | 58 | try { 59 | String pubspecPath = find( 60 | "pubspec.yaml", 61 | workingDirectory: flutterProjectDirectory.absolute.path, 62 | recursive: true, 63 | types: [FileSystemEntityType.file], 64 | ).toList().first; 65 | return right(pubspecPath); 66 | } on StateError catch (_) { 67 | return left( 68 | CommandFailure( 69 | cause: 70 | "pubspec.yaml not found in ${flutterProjectDirectory.path}", 71 | exitCode: 1, 72 | ), 73 | ); 74 | } 75 | }); 76 | 77 | Task> _getSemanticVersion(String pubspecPath) => 78 | Task>(() async { 79 | final pubspecString = File(pubspecPath).readAsStringSync(); 80 | final yaml = Pubspec.parse(pubspecString); 81 | if (!yaml.dependencies.containsKey("flutter")) { 82 | return left( 83 | CommandFailure( 84 | cause: "This pubspec is not flutter's pubspec.", 85 | exitCode: 1, 86 | ), 87 | ); 88 | } 89 | 90 | final semanticVersion = [ 91 | yaml.version!.major, 92 | yaml.version!.minor, 93 | yaml.version!.patch, 94 | ].join("."); 95 | return right(semanticVersion); 96 | }); 97 | } 98 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/appstore_connect_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dio/dio.dart'; 4 | import 'package:jose/jose.dart'; 5 | 6 | import 'ios_build.dart'; 7 | import 'provisioning_profile.dart'; 8 | 9 | const listProvisioningProfiles = 10 | "https://api.appstoreconnect.apple.com/v1/profiles"; 11 | 12 | // DateTime only has a milliecondsSinceEpoch, but JWT needs secondsSinceEpoch. 13 | // This is just a simple extension to add that capability to DateTime. 14 | extension SecondsSinceEpoch on DateTime { 15 | int get secondsSinceEpoch { 16 | return millisecondsSinceEpoch ~/ 1000; 17 | } 18 | 19 | DateTime fromSecondsSinceEpoch(int seconds) { 20 | return DateTime.fromMillisecondsSinceEpoch(seconds * 1000); 21 | } 22 | } 23 | 24 | class AppStoreConnectClient { 25 | final Dio _dio = Dio( 26 | BaseOptions( 27 | baseUrl: "https://api.appstoreconnect.apple.com/v1", 28 | ), 29 | ); 30 | 31 | final String apiPrivateKey; 32 | final String apiKeyId; 33 | final String issuerId; 34 | String bearerToken = ""; 35 | 36 | AppStoreConnectClient({ 37 | required this.apiPrivateKey, 38 | required this.apiKeyId, 39 | required this.issuerId, 40 | }) { 41 | bearerToken = Utils.appleClientSecret( 42 | privateKey: apiPrivateKey, 43 | keyId: apiKeyId, 44 | issuerId: issuerId, 45 | ); 46 | 47 | _dio.options.headers[HttpHeaders.authorizationHeader] = 48 | "Bearer $bearerToken"; 49 | } 50 | 51 | Future> listProfiles({ 52 | Map? queryParameters, 53 | }) async { 54 | final response = 55 | await _dio.get("/profiles", queryParameters: queryParameters); 56 | return AppstoreConnectApiResponse.fromJson(response.data) 57 | .data 58 | .map((e) => ProvisioningProfile.fromJson(e)) 59 | .toList(); 60 | } 61 | 62 | Future getProfile({ 63 | Map? queryParameters, 64 | required String profileId, 65 | }) async { 66 | final response = await _dio.get("/profiles/$profileId/bundleId", 67 | queryParameters: queryParameters); 68 | return response; 69 | } 70 | 71 | Future getLastTestflightBuildNumber({ 72 | required String appId, 73 | String? preReleaseVersion, 74 | }) async { 75 | final queryParameters = {}; 76 | queryParameters["filter[app]"] = appId; 77 | queryParameters["sort"] = "-version"; 78 | queryParameters["limit"] = 1; 79 | 80 | if (preReleaseVersion != null) { 81 | queryParameters["filter[preReleaseVersion.version]"] = preReleaseVersion; 82 | } 83 | final response = await _dio.get( 84 | "/builds", 85 | queryParameters: queryParameters, 86 | ); 87 | 88 | final builds = AppstoreConnectApiResponse.fromJson(response.data) 89 | .data 90 | .map((e) => IOSBuild.fromJson(e)); 91 | if (builds.isEmpty) { 92 | return "0"; 93 | } 94 | return builds.first.attributes.version; 95 | } 96 | } 97 | 98 | class Utils { 99 | static const audience = 'appstoreconnect-v1'; 100 | static const algorithm = 'ES256'; 101 | static const validDuration = 1200; 102 | 103 | static String appleClientSecret({ 104 | required String privateKey, 105 | required String keyId, 106 | required String issuerId, 107 | }) { 108 | final jwk = JsonWebKey.fromPem(privateKey, keyId: keyId); 109 | 110 | final claims = JsonWebTokenClaims.fromJson({ 111 | 'iss': issuerId, 112 | 'iat': DateTime.now().secondsSinceEpoch, 113 | 'exp': DateTime.now().secondsSinceEpoch + validDuration, 114 | 'aud': audience, 115 | }); 116 | 117 | final builder = JsonWebSignatureBuilder() 118 | ..jsonContent = claims.toJson() 119 | ..addRecipient(jwk, algorithm: algorithm); 120 | 121 | return builder.build().toCompactSerialization(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /packages/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /packages/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: "A new Flutter project." 3 | # The following line prevents the package from being accidentally published to 4 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 5 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 6 | 7 | # The following defines the version and build number for your application. 8 | # A version number is three numbers separated by dots, like 1.2.43 9 | # followed by an optional build number separated by a +. 10 | # Both the version and the builder number may be overridden in flutter 11 | # build by specifying --build-name and --build-number, respectively. 12 | # In Android, build-name is used as versionName while build-number used as versionCode. 13 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 14 | # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. 15 | # Read more about iOS versioning at 16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 17 | # In Windows, build-name is used as the major, minor, and patch parts 18 | # of the product and file versions while build-number is used as the build suffix. 19 | version: 1.0.4 20 | 21 | environment: 22 | sdk: '>=3.4.4 <4.0.0' 23 | 24 | # Dependencies specify other packages that your package needs in order to work. 25 | # To automatically upgrade your package dependencies to the latest versions 26 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 27 | # dependencies can be manually updated by changing the version numbers below to 28 | # the latest version available on pub.dev. To see which dependencies have newer 29 | # versions available, run `flutter pub outdated`. 30 | dependencies: 31 | flutter: 32 | sdk: flutter 33 | 34 | 35 | # The following adds the Cupertino Icons font to your application. 36 | # Use with the CupertinoIcons class for iOS style icons. 37 | cupertino_icons: ^1.0.6 38 | gambit_cli: 39 | path: ../gambit_cli 40 | 41 | dev_dependencies: 42 | flutter_test: 43 | sdk: flutter 44 | 45 | # The "flutter_lints" package below contains a set of recommended lints to 46 | # encourage good coding practices. The lint set provided by the package is 47 | # activated in the `analysis_options.yaml` file located at the root of your 48 | # package. See that file for information about deactivating specific lint 49 | # rules and activating additional ones. 50 | flutter_lints: ^3.0.0 51 | 52 | # For information on the generic Dart part of this file, see the 53 | # following page: https://dart.dev/tools/pub/pubspec 54 | 55 | # The following section is specific to Flutter packages. 56 | flutter: 57 | 58 | # The following line ensures that the Material Icons font is 59 | # included with your application, so that you can use the icons in 60 | # the material Icons class. 61 | uses-material-design: true 62 | 63 | # To add assets to your application, add an assets section, like this: 64 | # assets: 65 | # - images/a_dot_burr.jpeg 66 | # - images/a_dot_ham.jpeg 67 | 68 | # An image asset can refer to one or more resolution-specific "variants", see 69 | # https://flutter.dev/assets-and-images/#resolution-aware 70 | 71 | # For details regarding adding assets from package dependencies, see 72 | # https://flutter.dev/assets-and-images/#from-packages 73 | 74 | # To add custom fonts to your application, add a fonts section here, 75 | # in this "flutter" section. Each entry in this list should have a 76 | # "family" key with the font family name, and a "fonts" key with a 77 | # list giving the asset and other descriptors for the font. For 78 | # example: 79 | # fonts: 80 | # - family: Schyler 81 | # fonts: 82 | # - asset: fonts/Schyler-Regular.ttf 83 | # - asset: fonts/Schyler-Italic.ttf 84 | # style: italic 85 | # - family: Trajan Pro 86 | # fonts: 87 | # - asset: fonts/TrajanPro.ttf 88 | # - asset: fonts/TrajanPro_Bold.ttf 89 | # weight: 700 90 | # 91 | # For details regarding fonts from package dependencies, 92 | # see https://flutter.dev/custom-fonts/#from-packages 93 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/firebase/last_build_number/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | 5 | import '../../core/command_descriptor.dart'; 6 | import '../../core/exceptions.dart'; 7 | import '../../core/gambit_command.dart'; 8 | import 'package:googleapis_auth/auth_io.dart' as auth; 9 | import 'package:firebaseapis/firebaseappdistribution/v1.dart' 10 | as app_distribution; 11 | 12 | import '../../core/tasks.extensions.dart'; 13 | part 'descriptor.dart'; 14 | 15 | class LastBuildNumberCMD extends GambitCommand { 16 | late String serviceAccountJsonPath; 17 | late String projectId; 18 | late String appId; 19 | late String serviceAccoutJsonValue; 20 | late String bearerToken; 21 | LastBuildNumberCMD() : super(_LastBuildNumberDescriptor()); 22 | 23 | @override 24 | run() async { 25 | final runResult = await _parseArgs() 26 | .bindRight(_readServiceAccountJson) 27 | .bindRight(_getFirebaseAuthClient) 28 | .bindRight(_getLastBuildNumber) 29 | .run(); 30 | 31 | runResult.fold( 32 | (fail) { 33 | printError(fail.cause); 34 | exit(fail.exitCode); 35 | }, 36 | (success) { 37 | printSuccess(success); 38 | exit(0); 39 | }, 40 | ); 41 | } 42 | 43 | Task> _parseArgs() => 44 | Task>(() async { 45 | checkVerboseMode(); 46 | serviceAccountJsonPath = argResults![serviceAccountFilePathArgName]; 47 | projectId = argResults![projectIdArgName]; 48 | appId = argResults![appIdArgName]; 49 | return right(unit); 50 | }); 51 | 52 | Task> _readServiceAccountJson(_) => 53 | Task>(() async { 54 | try { 55 | serviceAccoutJsonValue = 56 | File(serviceAccountJsonPath).readAsStringSync(); 57 | return right(unit); 58 | } catch (ex) { 59 | return left( 60 | CommandFailure( 61 | cause: "Error reading .json service account file: $ex", 62 | ), 63 | ); 64 | } 65 | }); 66 | 67 | Task> 68 | _getFirebaseAuthClient(_) => 69 | Task>(() async { 70 | try { 71 | final authClient = await auth.clientViaServiceAccount( 72 | auth.ServiceAccountCredentials.fromJson(serviceAccoutJsonValue), 73 | [ 74 | app_distribution.FirebaseAppDistributionApi.cloudPlatformScope 75 | ], 76 | ); 77 | return right(authClient); 78 | } catch (ex) { 79 | return left( 80 | CommandFailure( 81 | cause: "Can't authentify your user in firebase: $ex", 82 | ), 83 | ); 84 | } 85 | }); 86 | 87 | Task> _getLastBuildNumber( 88 | auth.AutoRefreshingAuthClient authClient) => 89 | Task>(() async { 90 | List? releases; 91 | try { 92 | final lastReleaseResponse = 93 | await app_distribution.FirebaseAppDistributionApi(authClient) 94 | .projects 95 | .apps 96 | .releases 97 | .list( 98 | "projects/$projectId/apps/$appId", 99 | orderBy: "createTime desc", 100 | pageSize: 1, 101 | ); 102 | 103 | releases = lastReleaseResponse.releases; 104 | } catch (ex) { 105 | return left( 106 | CommandFailure( 107 | cause: 108 | "Can't get releases from Firebase App Distribution: $ex"), 109 | ); 110 | } 111 | 112 | if (releases == null || releases.isEmpty) { 113 | if (argResults![defaultNumberArgName] != null) { 114 | return right(argResults![defaultNumberArgName]); 115 | } 116 | return left( 117 | CommandFailure( 118 | cause: "No releases found.", 119 | ), 120 | ); 121 | } else { 122 | return right(releases.first.buildVersion!); 123 | } 124 | }); 125 | } 126 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/core/discord_embeds.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'discord_embeds.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$DiscordMessageEmbedImpl _$$DiscordMessageEmbedImplFromJson( 10 | Map json) => 11 | _$DiscordMessageEmbedImpl( 12 | title: json['title'] as String?, 13 | type: json['type'] as String?, 14 | description: json['description'] as String?, 15 | url: json['url'] as String?, 16 | timestamp: (json['timestamp'] as num?)?.toInt(), 17 | color: (json['color'] as num?)?.toInt(), 18 | footer: json['footer'] == null 19 | ? null 20 | : EmbededFooter.fromJson(json['footer'] as Map), 21 | image: json['image'] == null 22 | ? null 23 | : EmbededMedia.fromJson(json['image'] as Map), 24 | thumbnail: json['thumbnail'] == null 25 | ? null 26 | : EmbededMedia.fromJson(json['thumbnail'] as Map), 27 | video: json['video'] == null 28 | ? null 29 | : EmbededMedia.fromJson(json['video'] as Map), 30 | provider: json['provider'] == null 31 | ? null 32 | : EmbededProvider.fromJson(json['provider'] as Map), 33 | author: json['author'] == null 34 | ? null 35 | : EmbededAuthor.fromJson(json['author'] as Map), 36 | fields: (json['fields'] as List?) 37 | ?.map((e) => EmbededField.fromJson(e as Map)) 38 | .toList(), 39 | ); 40 | 41 | Map _$$DiscordMessageEmbedImplToJson( 42 | _$DiscordMessageEmbedImpl instance) => 43 | { 44 | 'title': instance.title, 45 | 'type': instance.type, 46 | 'description': instance.description, 47 | 'url': instance.url, 48 | 'timestamp': instance.timestamp, 49 | 'color': instance.color, 50 | 'footer': instance.footer, 51 | 'image': instance.image, 52 | 'thumbnail': instance.thumbnail, 53 | 'video': instance.video, 54 | 'provider': instance.provider, 55 | 'author': instance.author, 56 | 'fields': instance.fields, 57 | }; 58 | 59 | _$EmbededFooterImpl _$$EmbededFooterImplFromJson(Map json) => 60 | _$EmbededFooterImpl( 61 | text: json['text'] as String, 62 | iconUrl: json['icon_url'] as String?, 63 | proxyIconUrl: json['proxy_icon_url'] as String?, 64 | ); 65 | 66 | Map _$$EmbededFooterImplToJson(_$EmbededFooterImpl instance) => 67 | { 68 | 'text': instance.text, 69 | 'icon_url': instance.iconUrl, 70 | 'proxy_icon_url': instance.proxyIconUrl, 71 | }; 72 | 73 | _$EmbededMediaImpl _$$EmbededMediaImplFromJson(Map json) => 74 | _$EmbededMediaImpl( 75 | url: json['url'] as String, 76 | proxyUl: json['proxy_url'] as String?, 77 | height: (json['height'] as num?)?.toInt(), 78 | width: (json['width'] as num?)?.toInt(), 79 | ); 80 | 81 | Map _$$EmbededMediaImplToJson(_$EmbededMediaImpl instance) => 82 | { 83 | 'url': instance.url, 84 | 'proxy_url': instance.proxyUl, 85 | 'height': instance.height, 86 | 'width': instance.width, 87 | }; 88 | 89 | _$EmbededProviderImpl _$$EmbededProviderImplFromJson( 90 | Map json) => 91 | _$EmbededProviderImpl( 92 | name: json['name'] as String?, 93 | url: json['url'] as String?, 94 | ); 95 | 96 | Map _$$EmbededProviderImplToJson( 97 | _$EmbededProviderImpl instance) => 98 | { 99 | 'name': instance.name, 100 | 'url': instance.url, 101 | }; 102 | 103 | _$EmbededAuthorImpl _$$EmbededAuthorImplFromJson(Map json) => 104 | _$EmbededAuthorImpl( 105 | name: json['name'] as String, 106 | url: json['url'] as String?, 107 | iconUrl: json['icon_url'] as String?, 108 | proxyIconUrl: json['proxy_icon_url'] as String?, 109 | ); 110 | 111 | Map _$$EmbededAuthorImplToJson(_$EmbededAuthorImpl instance) => 112 | { 113 | 'name': instance.name, 114 | 'url': instance.url, 115 | 'icon_url': instance.iconUrl, 116 | 'proxy_icon_url': instance.proxyIconUrl, 117 | }; 118 | 119 | _$EmbededFieldImpl _$$EmbededFieldImplFromJson(Map json) => 120 | _$EmbededFieldImpl( 121 | name: json['name'] as String, 122 | value: json['value'] as String, 123 | inline: json['inline'] as bool?, 124 | ); 125 | 126 | Map _$$EmbededFieldImplToJson(_$EmbededFieldImpl instance) => 127 | { 128 | 'name': instance.name, 129 | 'value': instance.value, 130 | 'inline': instance.inline, 131 | }; 132 | -------------------------------------------------------------------------------- /packages/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() { 4 | runApp(const MyApp()); 5 | } 6 | 7 | class MyApp extends StatelessWidget { 8 | const MyApp({super.key}); 9 | 10 | // This widget is the root of your application. 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | title: 'Flutter Demo', 15 | theme: ThemeData( 16 | // This is the theme of your application. 17 | // 18 | // TRY THIS: Try running your application with "flutter run". You'll see 19 | // the application has a purple toolbar. Then, without quitting the app, 20 | // try changing the seedColor in the colorScheme below to Colors.green 21 | // and then invoke "hot reload" (save your changes or press the "hot 22 | // reload" button in a Flutter-supported IDE, or press "r" if you used 23 | // the command line to start the app). 24 | // 25 | // Notice that the counter didn't reset back to zero; the application 26 | // state is not lost during the reload. To reset the state, use hot 27 | // restart instead. 28 | // 29 | // This works for code too, not just values: Most code changes can be 30 | // tested with just a hot reload. 31 | colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), 32 | useMaterial3: true, 33 | ), 34 | home: const MyHomePage(title: 'Flutter Demo Home Page'), 35 | ); 36 | } 37 | } 38 | 39 | class MyHomePage extends StatefulWidget { 40 | const MyHomePage({super.key, required this.title}); 41 | 42 | // This widget is the home page of your application. It is stateful, meaning 43 | // that it has a State object (defined below) that contains fields that affect 44 | // how it looks. 45 | 46 | // This class is the configuration for the state. It holds the values (in this 47 | // case the title) provided by the parent (in this case the App widget) and 48 | // used by the build method of the State. Fields in a Widget subclass are 49 | // always marked "final". 50 | 51 | final String title; 52 | 53 | @override 54 | State createState() => _MyHomePageState(); 55 | } 56 | 57 | class _MyHomePageState extends State { 58 | int _counter = 0; 59 | 60 | void _incrementCounter() { 61 | setState(() { 62 | // This call to setState tells the Flutter framework that something has 63 | // changed in this State, which causes it to rerun the build method below 64 | // so that the display can reflect the updated values. If we changed 65 | // _counter without calling setState(), then the build method would not be 66 | // called again, and so nothing would appear to happen. 67 | _counter++; 68 | }); 69 | } 70 | 71 | @override 72 | Widget build(BuildContext context) { 73 | // This method is rerun every time setState is called, for instance as done 74 | // by the _incrementCounter method above. 75 | // 76 | // The Flutter framework has been optimized to make rerunning build methods 77 | // fast, so that you can just rebuild anything that needs updating rather 78 | // than having to individually change instances of widgets. 79 | return Scaffold( 80 | appBar: AppBar( 81 | // TRY THIS: Try changing the color here to a specific color (to 82 | // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar 83 | // change color while the other colors stay the same. 84 | backgroundColor: Theme.of(context).colorScheme.inversePrimary, 85 | // Here we take the value from the MyHomePage object that was created by 86 | // the App.build method, and use it to set our appbar title. 87 | title: Text(widget.title), 88 | ), 89 | body: Center( 90 | // Center is a layout widget. It takes a single child and positions it 91 | // in the middle of the parent. 92 | child: Column( 93 | // Column is also a layout widget. It takes a list of children and 94 | // arranges them vertically. By default, it sizes itself to fit its 95 | // children horizontally, and tries to be as tall as its parent. 96 | // 97 | // Column has various properties to control how it sizes itself and 98 | // how it positions its children. Here we use mainAxisAlignment to 99 | // center the children vertically; the main axis here is the vertical 100 | // axis because Columns are vertical (the cross axis would be 101 | // horizontal). 102 | // 103 | // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" 104 | // action in the IDE, or press "p" in the console), to see the 105 | // wireframe for each widget. 106 | mainAxisAlignment: MainAxisAlignment.center, 107 | children: [ 108 | const Text( 109 | 'You have pushed the button this many times:', 110 | ), 111 | Text( 112 | '$_counter', 113 | style: Theme.of(context).textTheme.headlineMedium, 114 | ), 115 | ], 116 | ), 117 | ), 118 | floatingActionButton: FloatingActionButton( 119 | onPressed: _incrementCounter, 120 | tooltip: 'Increment', 121 | child: const Icon(Icons.add), 122 | ), // This trailing comma makes auto-formatting nicer for build methods. 123 | ); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## 2024-08-19 7 | 8 | ### Changes 9 | 10 | --- 11 | 12 | Packages with breaking changes: 13 | 14 | - There are no breaking changes in this release. 15 | 16 | Packages with other changes: 17 | 18 | - [`example` - `v1.0.4`](#example---v104) 19 | - [`gambit_cli` - `v1.3.3`](#gambit_cli---v133) 20 | 21 | --- 22 | 23 | #### `example` - `v1.0.4` 24 | 25 | - **FIX**(testflight-last-build-number): fix parsing error. 26 | 27 | #### `gambit_cli` - `v1.3.3` 28 | 29 | - **FIX**(testflight-last-build-number): fix parsing error. 30 | 31 | 32 | ## 2024-08-06 33 | 34 | ### Changes 35 | 36 | --- 37 | 38 | Packages with breaking changes: 39 | 40 | - There are no breaking changes in this release. 41 | 42 | Packages with other changes: 43 | 44 | - [`gambit_cli` - `v1.3.2`](#gambit_cli---v132) 45 | - [`example` - `v1.0.3`](#example---v103) 46 | 47 | Packages with dependency updates only: 48 | 49 | > Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. 50 | 51 | - `example` - `v1.0.3` 52 | 53 | --- 54 | 55 | #### `gambit_cli` - `v1.3.2` 56 | 57 | - **FIX**(testflight-publish): fix xcrun command error and ipa file path with spaces. 58 | 59 | 60 | ## 2024-08-05 61 | 62 | ### Changes 63 | 64 | --- 65 | 66 | Packages with breaking changes: 67 | 68 | - There are no breaking changes in this release. 69 | 70 | Packages with other changes: 71 | 72 | - [`gambit_cli` - `v1.3.1`](#gambit_cli---v131) 73 | - [`example` - `v1.0.2`](#example---v102) 74 | 75 | Packages with dependency updates only: 76 | 77 | > Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. 78 | 79 | - `example` - `v1.0.2` 80 | 81 | --- 82 | 83 | #### `gambit_cli` - `v1.3.1` 84 | 85 | - **REFACTOR**(freezed): regen freezed. 86 | - **REFACTOR**: DioError deprecated, use DioException. 87 | - **FIX**(ios): ios testflight-last-build-number fixed response error. 88 | - **FIX**(get-app-version): Fix dans la lecture du pubspec suite bump pubspec_parse. 89 | 90 | 91 | ## 2024-08-05 92 | 93 | ### Changes 94 | 95 | --- 96 | 97 | Packages with breaking changes: 98 | 99 | - There are no breaking changes in this release. 100 | 101 | Packages with other changes: 102 | 103 | - [`gambit_cli` - `v1.3.1`](#gambit_cli---v131) 104 | - [`example` - `v1.0.1`](#example---v101) 105 | 106 | Packages with dependency updates only: 107 | 108 | > Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. 109 | 110 | - `example` - `v1.0.1` 111 | 112 | --- 113 | 114 | #### `gambit_cli` - `v1.3.1` 115 | 116 | - **REFACTOR**: DioError deprecated, use DioException. 117 | - **FIX**(get-app-version): Fix dans la lecture du pubspec suite bump pubspec_parse. 118 | 119 | # Changelog 120 | 121 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 122 | 123 | ## [1.2.0](https://github.com/MaVilleMonShopping/Gambit-cli/compare/gambit_cli-v1.1.1...gambit_cli-v1.2.0) (2022-08-24) 124 | 125 | 126 | ### Features 127 | 128 | * **appdistribution:** get last build number ([8262d6b](https://github.com/MaVilleMonShopping/Gambit-cli/commit/8262d6bcd37cb5fceb31798de34b100b8760e7d1)) 129 | * **firebase:** upload apk to firebase app distribution. ([6ffa4e1](https://github.com/MaVilleMonShopping/Gambit-cli/commit/6ffa4e1d182565194218ea1f108349dd04380b55)) 130 | * **firebase:** upload apk to firebase app distribution. ([6d694b2](https://github.com/MaVilleMonShopping/Gambit-cli/commit/6d694b21fb6384ca8a4c43829b163cc6babd173a)) 131 | * **firebase:** upload apk to firebase app distribution. ([c840ad7](https://github.com/MaVilleMonShopping/Gambit-cli/commit/c840ad7d966d6b75ab5dca898a3bacf571bad866)) 132 | * **firebase:** upload apk to firebase app distribution. ([1d1b73f](https://github.com/MaVilleMonShopping/Gambit-cli/commit/1d1b73f3dce2f77f1880d1635968214192b386d5)) 133 | 134 | 135 | ### Bug Fixes 136 | 137 | * testflight-last-build-number default to 0 ([b4872f3](https://github.com/MaVilleMonShopping/Gambit-cli/commit/b4872f36b1920f53f5d05063450fba04b6956f96)) 138 | * testflight-last-build-number default to 0 ([d78ac40](https://github.com/MaVilleMonShopping/Gambit-cli/commit/d78ac405dd4947666474eca17d278afd9e15e9a5)) 139 | 140 | ### [1.1.1](https://github.com/Danaru87/Gambit-cli/compare/v1.1.0...v1.1.1) (2022-05-17) 141 | 142 | 143 | ### Bug Fixes 144 | 145 | * testflight-last-build-number default to 0 ([b4872f3](https://github.com/Danaru87/Gambit-cli/commit/b4872f36b1920f53f5d05063450fba04b6956f96)) 146 | * testflight-last-build-number default to 0 ([d78ac40](https://github.com/Danaru87/Gambit-cli/commit/d78ac405dd4947666474eca17d278afd9e15e9a5)) 147 | 148 | ## [1.1.0](https://github.com/Danaru87/Gambit-cli/compare/v1.0.0...v1.1.0) (2022-05-08) 149 | 150 | 151 | ### Features 152 | 153 | * **appdistribution:** get last build number ([15d4418](https://github.com/Danaru87/Gambit-cli/commit/15d4418a3640cbaba04c84b2dac2e078d0cc9809)) 154 | 155 | ## 1.0.0 (2022-05-07) 156 | 157 | First release. 158 | 159 | Available commands: 160 | 161 | - ios get-provisioning-profiles 162 | - ios use-profile 163 | - ios testflight-last-build-number 164 | - ios testflight-publish 165 | - get-app-version 166 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/testflight_publish/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dcli/dcli.dart'; 5 | import 'package:path/path.dart'; 6 | 7 | import '../../core/command_descriptor.dart'; 8 | import '../../core/exceptions.dart'; 9 | import '../../core/gambit_command.dart'; 10 | import '../../core/tasks.extensions.dart'; 11 | import '../core/args_consts.dart'; 12 | 13 | part 'descriptor.dart'; 14 | 15 | class TestflightPublish extends GambitCommand { 16 | final Map altoolValidateArgs = {}; 17 | final Map altoolUploadArgs = {}; 18 | late String apiPrivateKey; 19 | late String apiKeyId; 20 | late String ipaPath; 21 | late String apiPrivateKeyFilename; 22 | late File privateKey; 23 | late int maxRetry; 24 | TestflightPublish() : super(TestflightPublishDescriptor()); 25 | 26 | @override 27 | void run() async { 28 | (await _configure() 29 | .bindRight(_installPrivateKey) 30 | .bindRight(_validate) 31 | .bindRight(_upload) 32 | .bind(_removePrivateKey) 33 | .run()) 34 | .fold( 35 | (fail) { 36 | printError(fail.cause); 37 | exit(fail.exitCode); 38 | }, 39 | (_) { 40 | printSuccess("App sent to Testflight"); 41 | exit(0); 42 | }, 43 | ); 44 | } 45 | 46 | Task> _configure() => Task>(() async { 47 | if (!Platform.isMacOS) { 48 | return left(CommandFailure( 49 | cause: 50 | "Only avalaible on MacOS, your are running gambit on ${Platform.operatingSystem}")); 51 | } 52 | checkVerboseMode(); 53 | print(yellow("Initializing")); 54 | apiKeyId = argResults![apiKeyIdArgName]; 55 | apiPrivateKey = argResults![apiPrivateKeyArgName]; 56 | 57 | // need to escape space in path for unix command 58 | // ignore: unnecessary_string_escapes 59 | ipaPath = argResults![ipPathArgName].replaceAll(" ", "\ "); 60 | maxRetry = int.tryParse(argResults![maxTryArgName]) ?? 1; 61 | 62 | altoolValidateArgs["--apiIssuer"] = argResults![issuerIdArgName]; 63 | altoolUploadArgs["--apiIssuer"] = argResults![issuerIdArgName]; 64 | 65 | altoolValidateArgs["--type"] = "ios"; 66 | altoolUploadArgs["--type"] = "ios"; 67 | 68 | altoolValidateArgs["--apiKey"] = apiKeyId; 69 | altoolUploadArgs["--apiKey"] = apiKeyId; 70 | 71 | altoolValidateArgs["--file"] = ipaPath; 72 | altoolUploadArgs["--file"] = ipaPath; 73 | 74 | printDebug(green("Initialization done !")); 75 | return right(unit); 76 | }); 77 | 78 | Task> _installPrivateKey(_) => 79 | Task>(() async { 80 | print(yellow("Saving api private key")); 81 | apiPrivateKeyFilename = "AuthKey_$apiKeyId.p8"; 82 | final privateKeyDir = Directory("$HOME/.appstoreconnect/private_keys"); 83 | privateKey = File( 84 | join( 85 | privateKeyDir.path, 86 | apiPrivateKeyFilename, 87 | ), 88 | ); 89 | try { 90 | privateKey.createSync(recursive: true); 91 | privateKey.writeAsStringSync(apiPrivateKey); 92 | printDebug(blue("Private key saved at ${privateKey.absolute.path}")); 93 | return right(unit); 94 | } catch (ex) { 95 | return left( 96 | CommandFailure( 97 | cause: "Can't save private key at ${privateKey.absolute.path}", 98 | ), 99 | ); 100 | } 101 | }); 102 | Task> _validate(_) => Task>(() async { 103 | print(yellow("Validating ipa...")); 104 | List argsXCrun = ["altool", "--validate-app"]; 105 | 106 | if (verboseEnabled) { 107 | argsXCrun.add("--show-progress"); 108 | } 109 | 110 | for (var entry in altoolValidateArgs.entries 111 | .where((element) => element.value != null)) { 112 | argsXCrun.add(entry.key); 113 | argsXCrun.add(entry.value); 114 | } 115 | try { 116 | final result = await Process.run("xcrun", argsXCrun); 117 | printDebug(result.stdout); 118 | if (result.exitCode != 0) { 119 | printDebug(result.stderr); 120 | return left(CommandFailure(cause: "Validation failed")); 121 | } 122 | return right(unit); 123 | } catch (ex) { 124 | printDebug(ex.toString()); 125 | return left(CommandFailure(cause: "Validation failed")); 126 | } 127 | }); 128 | 129 | Task> _upload(_) => Task>(() async { 130 | for (int i = 1; i <= maxRetry; i++) { 131 | print(yellow("Uploading ipa... (try $i/$maxRetry)")); 132 | try { 133 | await _uploadIpa(); 134 | return right(unit); 135 | } catch (ex) { 136 | printError("Error while uploading, retry..."); 137 | } 138 | } 139 | 140 | return left(CommandFailure(cause: "Can't upload ipa.")); 141 | }); 142 | 143 | Task> _removePrivateKey(GCTaskResult result) => 144 | Task>(() async { 145 | try { 146 | privateKey.deleteSync(); 147 | print(yellow("Private key deleted")); 148 | } catch (_) {} 149 | 150 | return result; 151 | }); 152 | 153 | Future _uploadIpa() async { 154 | List argsXCrun = ["altool", "--upload-app"]; 155 | 156 | if (verboseEnabled) { 157 | argsXCrun.add("--show-progress"); 158 | } 159 | 160 | for (var entry 161 | in altoolUploadArgs.entries.where((element) => element.value != null)) { 162 | argsXCrun.add(entry.key); 163 | argsXCrun.add(entry.value); 164 | } 165 | 166 | try { 167 | final result = await Process.run("xcrun", argsXCrun); 168 | printDebug(result.stdout); 169 | if (result.exitCode != 0) { 170 | printDebug(result.stderr); 171 | return false; 172 | } 173 | return true; 174 | } catch (ex) { 175 | printDebug(ex.toString()); 176 | return false; 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/get_provisioning_profiles/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | import 'dart:math'; 4 | import 'dart:typed_data'; 5 | 6 | import 'package:args/command_runner.dart'; 7 | import 'package:dartz/dartz.dart'; 8 | import 'package:dcli/dcli.dart'; 9 | import 'package:dio/dio.dart'; 10 | import 'package:path/path.dart'; 11 | 12 | import '../../core/command_descriptor.dart'; 13 | import '../../core/exceptions.dart'; 14 | import '../../core/gambit_command.dart'; 15 | import '../../core/tasks.extensions.dart'; 16 | import '../core/appstore_connect_utils.dart'; 17 | import '../core/args_consts.dart'; 18 | import '../core/provisioning_profile.dart'; 19 | part 'descriptor.dart'; 20 | 21 | class GetProvisioninProfile extends GambitCommand { 22 | late bool downloadAll; 23 | late String apiPrivateKey; 24 | late String apiKeyId; 25 | late String issuerId; 26 | late String? bundleId; 27 | late String profileType; 28 | late String outputFolderPath; 29 | late AppStoreConnectClient _appStoreConnectClient; 30 | 31 | late Directory provisioningProfileDirectory; 32 | GetProvisioninProfile() 33 | : super( 34 | _GetProvisoningProfileDescriptor(), 35 | ); 36 | 37 | @override 38 | void run() async { 39 | verboseEnabled = true; 40 | final runResult = await _init() 41 | .bindRight(_listProfiles) 42 | .bindRight(_filterProfiles) 43 | .bindRight(_saveProfiles) 44 | .run(); 45 | 46 | runResult.fold( 47 | (fail) { 48 | printError(fail.cause); 49 | exit(fail.exitCode); 50 | }, 51 | (success) { 52 | printSuccess("${success.length} Provisioning profile(s) saved !"); 53 | exit(0); 54 | }, 55 | ); 56 | } 57 | 58 | Task> _init() => Task>(() async { 59 | if (!Platform.isMacOS) { 60 | return left(CommandFailure( 61 | cause: 62 | "Only avalaible on MacOS, your are running gambit on ${Platform.operatingSystem}")); 63 | } 64 | downloadAll = argResults![alldArgName] ?? false; 65 | apiPrivateKey = argResults![apiPrivateKeyArgName]; 66 | apiKeyId = argResults![apiKeyIdArgName]; 67 | issuerId = argResults![issuerIdArgName]; 68 | bundleId = argResults![bundleIdArgName]; 69 | profileType = argResults![profileTypeArgName]; 70 | outputFolderPath = argResults![outputArgName]; 71 | 72 | provisioningProfileDirectory = Directory(outputFolderPath); 73 | 74 | if (downloadAll) { 75 | printDebug(yellow("Downloading all profiles")); 76 | } else if (bundleId == null) { 77 | throw UsageException(red("Use bundle-id argument or --all"), usage); 78 | } else { 79 | printDebug(yellow("Downloading profile for $bundleId")); 80 | } 81 | 82 | _appStoreConnectClient = AppStoreConnectClient( 83 | apiPrivateKey: apiPrivateKey, 84 | apiKeyId: apiKeyId, 85 | issuerId: issuerId, 86 | ); 87 | 88 | return right(unit); 89 | }); 90 | 91 | Task>> _listProfiles(Unit _) => 92 | Task>>(() async { 93 | try { 94 | final profiles = 95 | await _appStoreConnectClient.listProfiles(queryParameters: { 96 | "filter[profileType]": profileType, 97 | }); 98 | return right(profiles); 99 | } on DioException catch (ex) { 100 | return left( 101 | CommandFailure( 102 | cause: "Can't retrieve profiles: ${ex.response}", exitCode: 1), 103 | ); 104 | } 105 | }); 106 | 107 | Task>> _filterProfiles( 108 | List profiles) => 109 | Task>>(() async { 110 | if (downloadAll) { 111 | return right(profiles); 112 | } 113 | 114 | for (final prof in profiles) { 115 | final bundleResponse = 116 | await _appStoreConnectClient.getProfile(profileId: prof.id); 117 | if (bundleResponse.data["data"]["attributes"]["identifier"] == 118 | bundleId) { 119 | printDebug("Provisioning profile found !"); 120 | return right([prof]); 121 | } 122 | } 123 | return left( 124 | CommandFailure( 125 | cause: "No profile fond for bundleId: $bundleId", 126 | exitCode: 1, 127 | ), 128 | ); 129 | }); 130 | 131 | Task>> _saveProfiles( 132 | List toSave) => 133 | Task>>(() async { 134 | printDebug(yellow( 135 | "Saving profiles in: ${provisioningProfileDirectory.absolute.path}")); 136 | 137 | final filesPaths = []; 138 | for (final profile in toSave) { 139 | try { 140 | filesPaths.add( 141 | await _writeFile(profile), 142 | ); 143 | } catch (ex) { 144 | return left( 145 | CommandFailure( 146 | cause: "An error occured saving profile ${profile.fileName}", 147 | exitCode: 1, 148 | ), 149 | ); 150 | } 151 | } 152 | 153 | return right(filesPaths); 154 | }); 155 | 156 | Future _writeFile(ProvisioningProfile profile) async { 157 | final encodedString = profile.attributes.profileContent; 158 | Uint8List bytes = base64Decode(encodedString); 159 | File file = File( 160 | join(provisioningProfileDirectory.absolute.path, profile.fileName)); 161 | await file.writeAsBytes( 162 | bytes, 163 | mode: FileMode.write, 164 | ); 165 | print(blue( 166 | "Profile saved: ${file.absolute.path} ${await _getFileSize(file, 2)}")); 167 | 168 | return file.absolute.path; 169 | } 170 | 171 | Future _getFileSize(File file, int decimals) async { 172 | int bytes = await file.length(); 173 | if (bytes <= 0) return "0 B"; 174 | const suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; 175 | var i = (log(bytes) / log(1024)).floor(); 176 | return '${(bytes / pow(1024, i)).toStringAsFixed(decimals)} ${suffixes[i]}'; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/firebase/app_distribution/cmd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dcli/dcli.dart'; 5 | import 'package:dio/dio.dart'; 6 | import 'package:path/path.dart' as p; 7 | 8 | import '../../core/command_descriptor.dart'; 9 | import '../../core/exceptions.dart'; 10 | import '../../core/gambit_command.dart'; 11 | import '../../core/tasks.extensions.dart'; 12 | import 'package:googleapis_auth/auth_io.dart' as auth; 13 | import 'package:firebaseapis/firebaseappdistribution/v1.dart' 14 | as app_distribution; 15 | 16 | part 'descriptor.dart'; 17 | 18 | class AppDistributionCMD extends GambitCommand { 19 | late String serviceAccountJsonPath; 20 | late String serviceAccoutJsonValue; 21 | late String appId; 22 | late String projectId; 23 | late String apkPath; 24 | late File apk; 25 | late List testers; 26 | late List testGroups; 27 | late auth.AutoRefreshingAuthClient client; 28 | AppDistributionCMD() : super(_AppDistributionDescriptor()); 29 | 30 | @override 31 | run() async { 32 | final runResult = await _parseArgs() 33 | .bindRight(_readServiceAccountJson) 34 | .bindRight(_getFirebaseAuthClient) 35 | .bindRight(_loadApkFile) 36 | .bindRight((apk) => _uploadApk(apk)) 37 | .bindRight(_ditributeToGroups) 38 | .run(); 39 | 40 | runResult.fold( 41 | (fail) { 42 | printError(fail.cause); 43 | exit(fail.exitCode); 44 | }, 45 | (success) { 46 | printSuccess(""); 47 | exit(0); 48 | }, 49 | ); 50 | } 51 | 52 | Task> _parseArgs() => 53 | Task>(() async { 54 | checkVerboseMode(); 55 | serviceAccountJsonPath = argResults![serviceAccountFilePathArgName]; 56 | apkPath = argResults![apkPathArgName]; 57 | appId = argResults![appIdArgName]; 58 | projectId = argResults![projectIdArgName]; 59 | testers = ((argResults![testersArgName])?.split(",") as List?) 60 | ?.where((e) => e.isNotEmpty) 61 | .toList() ?? 62 | []; 63 | testGroups = 64 | ((argResults![testGroupsArgName])?.split(",") as List?) 65 | ?.where((e) => e.isNotEmpty) 66 | .toList() ?? 67 | []; 68 | return right(unit); 69 | }); 70 | 71 | Task> _readServiceAccountJson(_) => 72 | Task>(() async { 73 | try { 74 | serviceAccoutJsonValue = 75 | File(serviceAccountJsonPath).readAsStringSync(); 76 | return right(unit); 77 | } catch (ex) { 78 | return left( 79 | CommandFailure( 80 | cause: "Error reading .json service account file: $ex", 81 | ), 82 | ); 83 | } 84 | }); 85 | 86 | Task> _getFirebaseAuthClient(_) => 87 | Task>(() async { 88 | try { 89 | final authClient = await auth.clientViaServiceAccount( 90 | auth.ServiceAccountCredentials.fromJson(serviceAccoutJsonValue), 91 | [app_distribution.FirebaseAppDistributionApi.cloudPlatformScope], 92 | ); 93 | client = authClient; 94 | return right(unit); 95 | } catch (ex) { 96 | return left( 97 | CommandFailure( 98 | cause: "Can't authentify your user in firebase: $ex", 99 | ), 100 | ); 101 | } 102 | }); 103 | 104 | Task> _loadApkFile(_) => 105 | Task>(() async { 106 | try { 107 | printDebug("Getting APK"); 108 | apk = File(apkPath); 109 | if (apk.existsSync()) { 110 | return right(apk); 111 | } 112 | throw FileNotFoundException(apkPath); 113 | } catch (ex) { 114 | return left(CommandFailure(cause: ex.toString())); 115 | } 116 | }); 117 | 118 | Task> _uploadApk(File apk) => 119 | Task>(() async { 120 | final dioClient = Dio( 121 | BaseOptions( 122 | baseUrl: "https://firebaseappdistribution.googleapis.com", 123 | headers: { 124 | HttpHeaders.authorizationHeader: 125 | "Bearer ${client.credentials.accessToken.data}", 126 | "X-Goog-Upload-Protocol": "raw", 127 | "X-Goog-Upload-File-Name": p.basename(apk.path), 128 | }, 129 | ), 130 | ); 131 | 132 | printDebug("Uploading...."); 133 | 134 | final resp = await dioClient.post( 135 | "/upload/v1/projects/$projectId/apps/$appId/releases:upload", 136 | data: Stream.fromIterable((apk.readAsBytesSync().map((e) => [e]))), 137 | ); 138 | 139 | final responseData = Map.from(resp.data); 140 | final opeUri = responseData["name"] as String; 141 | bool done = false; 142 | Map? error; 143 | Map? data; 144 | Response? operationStatus; 145 | do { 146 | await Future.delayed(Duration(seconds: 1)); 147 | operationStatus = await dioClient.get("/v1/$opeUri"); 148 | data = Map.from(operationStatus.data); 149 | done = data["done"] ?? false; 150 | error = data["error"]; 151 | } while (!done); 152 | if (error != null) { 153 | return left(CommandFailure(cause: error.toString())); 154 | } 155 | 156 | printSuccess("APK Uploaded !", verboseSuffix: "\n$data"); 157 | return right(operationStatus.data["response"]["release"]["name"]); 158 | }); 159 | 160 | Task> _ditributeToGroups(String releaseUri) => 161 | Task>(() async { 162 | final dioClient = Dio( 163 | BaseOptions( 164 | baseUrl: "https://firebaseappdistribution.googleapis.com", 165 | headers: { 166 | HttpHeaders.authorizationHeader: 167 | "Bearer ${client.credentials.accessToken.data}", 168 | }, 169 | ), 170 | ); 171 | 172 | printDebug("Distributing...."); 173 | 174 | final data = {}; 175 | if (testers.isNotEmpty) { 176 | data["testerEmails"] = testers; 177 | } 178 | 179 | if (testGroups.isNotEmpty) { 180 | data["groupAliases"] = testGroups; 181 | } 182 | 183 | try { 184 | await dioClient.post( 185 | "/v1/$releaseUri:distribute", 186 | data: data, 187 | ); 188 | printSuccess("APK Distributed to: $data"); 189 | return right(unit); 190 | } catch (ex) { 191 | return left(CommandFailure(cause: ex.toString())); 192 | } 193 | }); 194 | } 195 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/discord/core/discord_message.freezed.dart: -------------------------------------------------------------------------------- 1 | // coverage:ignore-file 2 | // GENERATED CODE - DO NOT MODIFY BY HAND 3 | // ignore_for_file: type=lint 4 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark 5 | 6 | part of 'discord_message.dart'; 7 | 8 | // ************************************************************************** 9 | // FreezedGenerator 10 | // ************************************************************************** 11 | 12 | T _$identity(T value) => value; 13 | 14 | final _privateConstructorUsedError = UnsupportedError( 15 | 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); 16 | 17 | DiscordMessage _$DiscordMessageFromJson(Map json) { 18 | return _DiscordMessage.fromJson(json); 19 | } 20 | 21 | /// @nodoc 22 | mixin _$DiscordMessage { 23 | String get content => throw _privateConstructorUsedError; 24 | String? get username => throw _privateConstructorUsedError; 25 | @JsonKey(name: "avatar_url") 26 | String? get avatarUrl => throw _privateConstructorUsedError; 27 | bool? get tts => throw _privateConstructorUsedError; 28 | List? get embeds => throw _privateConstructorUsedError; 29 | 30 | /// Serializes this DiscordMessage to a JSON map. 31 | Map toJson() => throw _privateConstructorUsedError; 32 | 33 | /// Create a copy of DiscordMessage 34 | /// with the given fields replaced by the non-null parameter values. 35 | @JsonKey(includeFromJson: false, includeToJson: false) 36 | $DiscordMessageCopyWith get copyWith => 37 | throw _privateConstructorUsedError; 38 | } 39 | 40 | /// @nodoc 41 | abstract class $DiscordMessageCopyWith<$Res> { 42 | factory $DiscordMessageCopyWith( 43 | DiscordMessage value, $Res Function(DiscordMessage) then) = 44 | _$DiscordMessageCopyWithImpl<$Res, DiscordMessage>; 45 | @useResult 46 | $Res call( 47 | {String content, 48 | String? username, 49 | @JsonKey(name: "avatar_url") String? avatarUrl, 50 | bool? tts, 51 | List? embeds}); 52 | } 53 | 54 | /// @nodoc 55 | class _$DiscordMessageCopyWithImpl<$Res, $Val extends DiscordMessage> 56 | implements $DiscordMessageCopyWith<$Res> { 57 | _$DiscordMessageCopyWithImpl(this._value, this._then); 58 | 59 | // ignore: unused_field 60 | final $Val _value; 61 | // ignore: unused_field 62 | final $Res Function($Val) _then; 63 | 64 | /// Create a copy of DiscordMessage 65 | /// with the given fields replaced by the non-null parameter values. 66 | @pragma('vm:prefer-inline') 67 | @override 68 | $Res call({ 69 | Object? content = null, 70 | Object? username = freezed, 71 | Object? avatarUrl = freezed, 72 | Object? tts = freezed, 73 | Object? embeds = freezed, 74 | }) { 75 | return _then(_value.copyWith( 76 | content: null == content 77 | ? _value.content 78 | : content // ignore: cast_nullable_to_non_nullable 79 | as String, 80 | username: freezed == username 81 | ? _value.username 82 | : username // ignore: cast_nullable_to_non_nullable 83 | as String?, 84 | avatarUrl: freezed == avatarUrl 85 | ? _value.avatarUrl 86 | : avatarUrl // ignore: cast_nullable_to_non_nullable 87 | as String?, 88 | tts: freezed == tts 89 | ? _value.tts 90 | : tts // ignore: cast_nullable_to_non_nullable 91 | as bool?, 92 | embeds: freezed == embeds 93 | ? _value.embeds 94 | : embeds // ignore: cast_nullable_to_non_nullable 95 | as List?, 96 | ) as $Val); 97 | } 98 | } 99 | 100 | /// @nodoc 101 | abstract class _$$DiscordMessageImplCopyWith<$Res> 102 | implements $DiscordMessageCopyWith<$Res> { 103 | factory _$$DiscordMessageImplCopyWith(_$DiscordMessageImpl value, 104 | $Res Function(_$DiscordMessageImpl) then) = 105 | __$$DiscordMessageImplCopyWithImpl<$Res>; 106 | @override 107 | @useResult 108 | $Res call( 109 | {String content, 110 | String? username, 111 | @JsonKey(name: "avatar_url") String? avatarUrl, 112 | bool? tts, 113 | List? embeds}); 114 | } 115 | 116 | /// @nodoc 117 | class __$$DiscordMessageImplCopyWithImpl<$Res> 118 | extends _$DiscordMessageCopyWithImpl<$Res, _$DiscordMessageImpl> 119 | implements _$$DiscordMessageImplCopyWith<$Res> { 120 | __$$DiscordMessageImplCopyWithImpl( 121 | _$DiscordMessageImpl _value, $Res Function(_$DiscordMessageImpl) _then) 122 | : super(_value, _then); 123 | 124 | /// Create a copy of DiscordMessage 125 | /// with the given fields replaced by the non-null parameter values. 126 | @pragma('vm:prefer-inline') 127 | @override 128 | $Res call({ 129 | Object? content = null, 130 | Object? username = freezed, 131 | Object? avatarUrl = freezed, 132 | Object? tts = freezed, 133 | Object? embeds = freezed, 134 | }) { 135 | return _then(_$DiscordMessageImpl( 136 | content: null == content 137 | ? _value.content 138 | : content // ignore: cast_nullable_to_non_nullable 139 | as String, 140 | username: freezed == username 141 | ? _value.username 142 | : username // ignore: cast_nullable_to_non_nullable 143 | as String?, 144 | avatarUrl: freezed == avatarUrl 145 | ? _value.avatarUrl 146 | : avatarUrl // ignore: cast_nullable_to_non_nullable 147 | as String?, 148 | tts: freezed == tts 149 | ? _value.tts 150 | : tts // ignore: cast_nullable_to_non_nullable 151 | as bool?, 152 | embeds: freezed == embeds 153 | ? _value._embeds 154 | : embeds // ignore: cast_nullable_to_non_nullable 155 | as List?, 156 | )); 157 | } 158 | } 159 | 160 | /// @nodoc 161 | @JsonSerializable() 162 | class _$DiscordMessageImpl implements _DiscordMessage { 163 | const _$DiscordMessageImpl( 164 | {this.content = "", 165 | this.username, 166 | @JsonKey(name: "avatar_url") this.avatarUrl, 167 | this.tts, 168 | final List? embeds}) 169 | : _embeds = embeds; 170 | 171 | factory _$DiscordMessageImpl.fromJson(Map json) => 172 | _$$DiscordMessageImplFromJson(json); 173 | 174 | @override 175 | @JsonKey() 176 | final String content; 177 | @override 178 | final String? username; 179 | @override 180 | @JsonKey(name: "avatar_url") 181 | final String? avatarUrl; 182 | @override 183 | final bool? tts; 184 | final List? _embeds; 185 | @override 186 | List? get embeds { 187 | final value = _embeds; 188 | if (value == null) return null; 189 | if (_embeds is EqualUnmodifiableListView) return _embeds; 190 | // ignore: implicit_dynamic_type 191 | return EqualUnmodifiableListView(value); 192 | } 193 | 194 | @override 195 | String toString() { 196 | return 'DiscordMessage(content: $content, username: $username, avatarUrl: $avatarUrl, tts: $tts, embeds: $embeds)'; 197 | } 198 | 199 | @override 200 | bool operator ==(Object other) { 201 | return identical(this, other) || 202 | (other.runtimeType == runtimeType && 203 | other is _$DiscordMessageImpl && 204 | (identical(other.content, content) || other.content == content) && 205 | (identical(other.username, username) || 206 | other.username == username) && 207 | (identical(other.avatarUrl, avatarUrl) || 208 | other.avatarUrl == avatarUrl) && 209 | (identical(other.tts, tts) || other.tts == tts) && 210 | const DeepCollectionEquality().equals(other._embeds, _embeds)); 211 | } 212 | 213 | @JsonKey(includeFromJson: false, includeToJson: false) 214 | @override 215 | int get hashCode => Object.hash(runtimeType, content, username, avatarUrl, 216 | tts, const DeepCollectionEquality().hash(_embeds)); 217 | 218 | /// Create a copy of DiscordMessage 219 | /// with the given fields replaced by the non-null parameter values. 220 | @JsonKey(includeFromJson: false, includeToJson: false) 221 | @override 222 | @pragma('vm:prefer-inline') 223 | _$$DiscordMessageImplCopyWith<_$DiscordMessageImpl> get copyWith => 224 | __$$DiscordMessageImplCopyWithImpl<_$DiscordMessageImpl>( 225 | this, _$identity); 226 | 227 | @override 228 | Map toJson() { 229 | return _$$DiscordMessageImplToJson( 230 | this, 231 | ); 232 | } 233 | } 234 | 235 | abstract class _DiscordMessage implements DiscordMessage { 236 | const factory _DiscordMessage( 237 | {final String content, 238 | final String? username, 239 | @JsonKey(name: "avatar_url") final String? avatarUrl, 240 | final bool? tts, 241 | final List? embeds}) = _$DiscordMessageImpl; 242 | 243 | factory _DiscordMessage.fromJson(Map json) = 244 | _$DiscordMessageImpl.fromJson; 245 | 246 | @override 247 | String get content; 248 | @override 249 | String? get username; 250 | @override 251 | @JsonKey(name: "avatar_url") 252 | String? get avatarUrl; 253 | @override 254 | bool? get tts; 255 | @override 256 | List? get embeds; 257 | 258 | /// Create a copy of DiscordMessage 259 | /// with the given fields replaced by the non-null parameter values. 260 | @override 261 | @JsonKey(includeFromJson: false, includeToJson: false) 262 | _$$DiscordMessageImplCopyWith<_$DiscordMessageImpl> get copyWith => 263 | throw _privateConstructorUsedError; 264 | } 265 | -------------------------------------------------------------------------------- /packages/gambit_cli/lib/src/ios/core/ios_build.freezed.dart: -------------------------------------------------------------------------------- 1 | // coverage:ignore-file 2 | // GENERATED CODE - DO NOT MODIFY BY HAND 3 | // ignore_for_file: type=lint 4 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark 5 | 6 | part of 'ios_build.dart'; 7 | 8 | // ************************************************************************** 9 | // FreezedGenerator 10 | // ************************************************************************** 11 | 12 | T _$identity(T value) => value; 13 | 14 | final _privateConstructorUsedError = UnsupportedError( 15 | 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); 16 | 17 | IOSBuild _$IOSBuildFromJson(Map json) { 18 | return _IOSBuild.fromJson(json); 19 | } 20 | 21 | /// @nodoc 22 | mixin _$IOSBuild { 23 | IOSBuildAttributes get attributes => throw _privateConstructorUsedError; 24 | String get id => throw _privateConstructorUsedError; 25 | String get type => throw _privateConstructorUsedError; 26 | 27 | /// Serializes this IOSBuild to a JSON map. 28 | Map toJson() => throw _privateConstructorUsedError; 29 | 30 | /// Create a copy of IOSBuild 31 | /// with the given fields replaced by the non-null parameter values. 32 | @JsonKey(includeFromJson: false, includeToJson: false) 33 | $IOSBuildCopyWith get copyWith => 34 | throw _privateConstructorUsedError; 35 | } 36 | 37 | /// @nodoc 38 | abstract class $IOSBuildCopyWith<$Res> { 39 | factory $IOSBuildCopyWith(IOSBuild value, $Res Function(IOSBuild) then) = 40 | _$IOSBuildCopyWithImpl<$Res, IOSBuild>; 41 | @useResult 42 | $Res call({IOSBuildAttributes attributes, String id, String type}); 43 | 44 | $IOSBuildAttributesCopyWith<$Res> get attributes; 45 | } 46 | 47 | /// @nodoc 48 | class _$IOSBuildCopyWithImpl<$Res, $Val extends IOSBuild> 49 | implements $IOSBuildCopyWith<$Res> { 50 | _$IOSBuildCopyWithImpl(this._value, this._then); 51 | 52 | // ignore: unused_field 53 | final $Val _value; 54 | // ignore: unused_field 55 | final $Res Function($Val) _then; 56 | 57 | /// Create a copy of IOSBuild 58 | /// with the given fields replaced by the non-null parameter values. 59 | @pragma('vm:prefer-inline') 60 | @override 61 | $Res call({ 62 | Object? attributes = null, 63 | Object? id = null, 64 | Object? type = null, 65 | }) { 66 | return _then(_value.copyWith( 67 | attributes: null == attributes 68 | ? _value.attributes 69 | : attributes // ignore: cast_nullable_to_non_nullable 70 | as IOSBuildAttributes, 71 | id: null == id 72 | ? _value.id 73 | : id // ignore: cast_nullable_to_non_nullable 74 | as String, 75 | type: null == type 76 | ? _value.type 77 | : type // ignore: cast_nullable_to_non_nullable 78 | as String, 79 | ) as $Val); 80 | } 81 | 82 | /// Create a copy of IOSBuild 83 | /// with the given fields replaced by the non-null parameter values. 84 | @override 85 | @pragma('vm:prefer-inline') 86 | $IOSBuildAttributesCopyWith<$Res> get attributes { 87 | return $IOSBuildAttributesCopyWith<$Res>(_value.attributes, (value) { 88 | return _then(_value.copyWith(attributes: value) as $Val); 89 | }); 90 | } 91 | } 92 | 93 | /// @nodoc 94 | abstract class _$$IOSBuildImplCopyWith<$Res> 95 | implements $IOSBuildCopyWith<$Res> { 96 | factory _$$IOSBuildImplCopyWith( 97 | _$IOSBuildImpl value, $Res Function(_$IOSBuildImpl) then) = 98 | __$$IOSBuildImplCopyWithImpl<$Res>; 99 | @override 100 | @useResult 101 | $Res call({IOSBuildAttributes attributes, String id, String type}); 102 | 103 | @override 104 | $IOSBuildAttributesCopyWith<$Res> get attributes; 105 | } 106 | 107 | /// @nodoc 108 | class __$$IOSBuildImplCopyWithImpl<$Res> 109 | extends _$IOSBuildCopyWithImpl<$Res, _$IOSBuildImpl> 110 | implements _$$IOSBuildImplCopyWith<$Res> { 111 | __$$IOSBuildImplCopyWithImpl( 112 | _$IOSBuildImpl _value, $Res Function(_$IOSBuildImpl) _then) 113 | : super(_value, _then); 114 | 115 | /// Create a copy of IOSBuild 116 | /// with the given fields replaced by the non-null parameter values. 117 | @pragma('vm:prefer-inline') 118 | @override 119 | $Res call({ 120 | Object? attributes = null, 121 | Object? id = null, 122 | Object? type = null, 123 | }) { 124 | return _then(_$IOSBuildImpl( 125 | attributes: null == attributes 126 | ? _value.attributes 127 | : attributes // ignore: cast_nullable_to_non_nullable 128 | as IOSBuildAttributes, 129 | id: null == id 130 | ? _value.id 131 | : id // ignore: cast_nullable_to_non_nullable 132 | as String, 133 | type: null == type 134 | ? _value.type 135 | : type // ignore: cast_nullable_to_non_nullable 136 | as String, 137 | )); 138 | } 139 | } 140 | 141 | /// @nodoc 142 | @JsonSerializable() 143 | class _$IOSBuildImpl implements _IOSBuild { 144 | const _$IOSBuildImpl( 145 | {required this.attributes, required this.id, required this.type}); 146 | 147 | factory _$IOSBuildImpl.fromJson(Map json) => 148 | _$$IOSBuildImplFromJson(json); 149 | 150 | @override 151 | final IOSBuildAttributes attributes; 152 | @override 153 | final String id; 154 | @override 155 | final String type; 156 | 157 | @override 158 | String toString() { 159 | return 'IOSBuild(attributes: $attributes, id: $id, type: $type)'; 160 | } 161 | 162 | @override 163 | bool operator ==(Object other) { 164 | return identical(this, other) || 165 | (other.runtimeType == runtimeType && 166 | other is _$IOSBuildImpl && 167 | (identical(other.attributes, attributes) || 168 | other.attributes == attributes) && 169 | (identical(other.id, id) || other.id == id) && 170 | (identical(other.type, type) || other.type == type)); 171 | } 172 | 173 | @JsonKey(includeFromJson: false, includeToJson: false) 174 | @override 175 | int get hashCode => Object.hash(runtimeType, attributes, id, type); 176 | 177 | /// Create a copy of IOSBuild 178 | /// with the given fields replaced by the non-null parameter values. 179 | @JsonKey(includeFromJson: false, includeToJson: false) 180 | @override 181 | @pragma('vm:prefer-inline') 182 | _$$IOSBuildImplCopyWith<_$IOSBuildImpl> get copyWith => 183 | __$$IOSBuildImplCopyWithImpl<_$IOSBuildImpl>(this, _$identity); 184 | 185 | @override 186 | Map toJson() { 187 | return _$$IOSBuildImplToJson( 188 | this, 189 | ); 190 | } 191 | } 192 | 193 | abstract class _IOSBuild implements IOSBuild { 194 | const factory _IOSBuild( 195 | {required final IOSBuildAttributes attributes, 196 | required final String id, 197 | required final String type}) = _$IOSBuildImpl; 198 | 199 | factory _IOSBuild.fromJson(Map json) = 200 | _$IOSBuildImpl.fromJson; 201 | 202 | @override 203 | IOSBuildAttributes get attributes; 204 | @override 205 | String get id; 206 | @override 207 | String get type; 208 | 209 | /// Create a copy of IOSBuild 210 | /// with the given fields replaced by the non-null parameter values. 211 | @override 212 | @JsonKey(includeFromJson: false, includeToJson: false) 213 | _$$IOSBuildImplCopyWith<_$IOSBuildImpl> get copyWith => 214 | throw _privateConstructorUsedError; 215 | } 216 | 217 | IOSBuildAttributes _$IOSBuildAttributesFromJson(Map json) { 218 | return _IOSBuildAttributes.fromJson(json); 219 | } 220 | 221 | /// @nodoc 222 | mixin _$IOSBuildAttributes { 223 | String get version => throw _privateConstructorUsedError; 224 | String get processingState => throw _privateConstructorUsedError; 225 | 226 | /// Serializes this IOSBuildAttributes to a JSON map. 227 | Map toJson() => throw _privateConstructorUsedError; 228 | 229 | /// Create a copy of IOSBuildAttributes 230 | /// with the given fields replaced by the non-null parameter values. 231 | @JsonKey(includeFromJson: false, includeToJson: false) 232 | $IOSBuildAttributesCopyWith get copyWith => 233 | throw _privateConstructorUsedError; 234 | } 235 | 236 | /// @nodoc 237 | abstract class $IOSBuildAttributesCopyWith<$Res> { 238 | factory $IOSBuildAttributesCopyWith( 239 | IOSBuildAttributes value, $Res Function(IOSBuildAttributes) then) = 240 | _$IOSBuildAttributesCopyWithImpl<$Res, IOSBuildAttributes>; 241 | @useResult 242 | $Res call({String version, String processingState}); 243 | } 244 | 245 | /// @nodoc 246 | class _$IOSBuildAttributesCopyWithImpl<$Res, $Val extends IOSBuildAttributes> 247 | implements $IOSBuildAttributesCopyWith<$Res> { 248 | _$IOSBuildAttributesCopyWithImpl(this._value, this._then); 249 | 250 | // ignore: unused_field 251 | final $Val _value; 252 | // ignore: unused_field 253 | final $Res Function($Val) _then; 254 | 255 | /// Create a copy of IOSBuildAttributes 256 | /// with the given fields replaced by the non-null parameter values. 257 | @pragma('vm:prefer-inline') 258 | @override 259 | $Res call({ 260 | Object? version = null, 261 | Object? processingState = null, 262 | }) { 263 | return _then(_value.copyWith( 264 | version: null == version 265 | ? _value.version 266 | : version // ignore: cast_nullable_to_non_nullable 267 | as String, 268 | processingState: null == processingState 269 | ? _value.processingState 270 | : processingState // ignore: cast_nullable_to_non_nullable 271 | as String, 272 | ) as $Val); 273 | } 274 | } 275 | 276 | /// @nodoc 277 | abstract class _$$IOSBuildAttributesImplCopyWith<$Res> 278 | implements $IOSBuildAttributesCopyWith<$Res> { 279 | factory _$$IOSBuildAttributesImplCopyWith(_$IOSBuildAttributesImpl value, 280 | $Res Function(_$IOSBuildAttributesImpl) then) = 281 | __$$IOSBuildAttributesImplCopyWithImpl<$Res>; 282 | @override 283 | @useResult 284 | $Res call({String version, String processingState}); 285 | } 286 | 287 | /// @nodoc 288 | class __$$IOSBuildAttributesImplCopyWithImpl<$Res> 289 | extends _$IOSBuildAttributesCopyWithImpl<$Res, _$IOSBuildAttributesImpl> 290 | implements _$$IOSBuildAttributesImplCopyWith<$Res> { 291 | __$$IOSBuildAttributesImplCopyWithImpl(_$IOSBuildAttributesImpl _value, 292 | $Res Function(_$IOSBuildAttributesImpl) _then) 293 | : super(_value, _then); 294 | 295 | /// Create a copy of IOSBuildAttributes 296 | /// with the given fields replaced by the non-null parameter values. 297 | @pragma('vm:prefer-inline') 298 | @override 299 | $Res call({ 300 | Object? version = null, 301 | Object? processingState = null, 302 | }) { 303 | return _then(_$IOSBuildAttributesImpl( 304 | version: null == version 305 | ? _value.version 306 | : version // ignore: cast_nullable_to_non_nullable 307 | as String, 308 | processingState: null == processingState 309 | ? _value.processingState 310 | : processingState // ignore: cast_nullable_to_non_nullable 311 | as String, 312 | )); 313 | } 314 | } 315 | 316 | /// @nodoc 317 | @JsonSerializable() 318 | class _$IOSBuildAttributesImpl implements _IOSBuildAttributes { 319 | const _$IOSBuildAttributesImpl( 320 | {required this.version, required this.processingState}); 321 | 322 | factory _$IOSBuildAttributesImpl.fromJson(Map json) => 323 | _$$IOSBuildAttributesImplFromJson(json); 324 | 325 | @override 326 | final String version; 327 | @override 328 | final String processingState; 329 | 330 | @override 331 | String toString() { 332 | return 'IOSBuildAttributes(version: $version, processingState: $processingState)'; 333 | } 334 | 335 | @override 336 | bool operator ==(Object other) { 337 | return identical(this, other) || 338 | (other.runtimeType == runtimeType && 339 | other is _$IOSBuildAttributesImpl && 340 | (identical(other.version, version) || other.version == version) && 341 | (identical(other.processingState, processingState) || 342 | other.processingState == processingState)); 343 | } 344 | 345 | @JsonKey(includeFromJson: false, includeToJson: false) 346 | @override 347 | int get hashCode => Object.hash(runtimeType, version, processingState); 348 | 349 | /// Create a copy of IOSBuildAttributes 350 | /// with the given fields replaced by the non-null parameter values. 351 | @JsonKey(includeFromJson: false, includeToJson: false) 352 | @override 353 | @pragma('vm:prefer-inline') 354 | _$$IOSBuildAttributesImplCopyWith<_$IOSBuildAttributesImpl> get copyWith => 355 | __$$IOSBuildAttributesImplCopyWithImpl<_$IOSBuildAttributesImpl>( 356 | this, _$identity); 357 | 358 | @override 359 | Map toJson() { 360 | return _$$IOSBuildAttributesImplToJson( 361 | this, 362 | ); 363 | } 364 | } 365 | 366 | abstract class _IOSBuildAttributes implements IOSBuildAttributes { 367 | const factory _IOSBuildAttributes( 368 | {required final String version, 369 | required final String processingState}) = _$IOSBuildAttributesImpl; 370 | 371 | factory _IOSBuildAttributes.fromJson(Map json) = 372 | _$IOSBuildAttributesImpl.fromJson; 373 | 374 | @override 375 | String get version; 376 | @override 377 | String get processingState; 378 | 379 | /// Create a copy of IOSBuildAttributes 380 | /// with the given fields replaced by the non-null parameter values. 381 | @override 382 | @JsonKey(includeFromJson: false, includeToJson: false) 383 | _$$IOSBuildAttributesImplCopyWith<_$IOSBuildAttributesImpl> get copyWith => 384 | throw _privateConstructorUsedError; 385 | } 386 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | ansi_styles: 5 | dependency: transitive 6 | description: 7 | name: ansi_styles 8 | sha256: "9c656cc12b3c27b17dd982b2cc5c0cfdfbdabd7bc8f3ae5e8542d9867b47ce8a" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "0.3.2+1" 12 | archive: 13 | dependency: transitive 14 | description: 15 | name: archive 16 | sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "3.6.1" 20 | args: 21 | dependency: transitive 22 | description: 23 | name: args 24 | sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.5.0" 28 | async: 29 | dependency: transitive 30 | description: 31 | name: async 32 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.11.0" 36 | boolean_selector: 37 | dependency: transitive 38 | description: 39 | name: boolean_selector 40 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "2.1.1" 44 | characters: 45 | dependency: transitive 46 | description: 47 | name: characters 48 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.0" 52 | charcode: 53 | dependency: transitive 54 | description: 55 | name: charcode 56 | sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.1" 60 | chunked_stream: 61 | dependency: transitive 62 | description: 63 | name: chunked_stream 64 | sha256: b2fde5f81d780f0c1699b8347cae2e413412ae947fc6e64727cc48c6bb54c95c 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.4.2" 68 | circular_buffer: 69 | dependency: transitive 70 | description: 71 | name: circular_buffer 72 | sha256: "2889afcfc97aa0d9a4930ae5fdf206aea7d0ac88a3649acec9130565cd8f45d8" 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "0.11.0" 76 | cli_launcher: 77 | dependency: transitive 78 | description: 79 | name: cli_launcher 80 | sha256: "5e7e0282b79e8642edd6510ee468ae2976d847a0a29b3916e85f5fa1bfe24005" 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "0.3.1" 84 | cli_util: 85 | dependency: transitive 86 | description: 87 | name: cli_util 88 | sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "0.4.1" 92 | clock: 93 | dependency: transitive 94 | description: 95 | name: clock 96 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "1.1.1" 100 | collection: 101 | dependency: transitive 102 | description: 103 | name: collection 104 | sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "1.19.0" 108 | conventional_commit: 109 | dependency: transitive 110 | description: 111 | name: conventional_commit 112 | sha256: dec15ad1118f029c618651a4359eb9135d8b88f761aa24e4016d061cd45948f2 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "0.6.0+1" 116 | convert: 117 | dependency: transitive 118 | description: 119 | name: convert 120 | sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" 121 | url: "https://pub.dev" 122 | source: hosted 123 | version: "3.1.1" 124 | crypto: 125 | dependency: transitive 126 | description: 127 | name: crypto 128 | sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab 129 | url: "https://pub.dev" 130 | source: hosted 131 | version: "3.0.3" 132 | csv: 133 | dependency: transitive 134 | description: 135 | name: csv 136 | sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c 137 | url: "https://pub.dev" 138 | source: hosted 139 | version: "6.0.0" 140 | dart_console: 141 | dependency: transitive 142 | description: 143 | name: dart_console 144 | sha256: eae9ddd7bb69477a6e9821c75d575874e290887da09292732a35ab510d1de713 145 | url: "https://pub.dev" 146 | source: hosted 147 | version: "4.1.0" 148 | dcli: 149 | dependency: "direct dev" 150 | description: 151 | name: dcli 152 | sha256: d3df6c340c2015159578655e94a87560098d5052e23f8b10403f2f31f715b8de 153 | url: "https://pub.dev" 154 | source: hosted 155 | version: "5.0.0" 156 | dcli_common: 157 | dependency: transitive 158 | description: 159 | name: dcli_common 160 | sha256: d342b5eb461b0ce72fc7ccdb72b234456b3878fc26c37a8a1aef209eaaf089fa 161 | url: "https://pub.dev" 162 | source: hosted 163 | version: "5.0.0" 164 | dcli_core: 165 | dependency: transitive 166 | description: 167 | name: dcli_core 168 | sha256: "752baf94176d5b0e3100ec0c47d07e07f3590878ebf2b5a1e8e85fcde712b372" 169 | url: "https://pub.dev" 170 | source: hosted 171 | version: "5.0.0" 172 | dcli_terminal: 173 | dependency: transitive 174 | description: 175 | name: dcli_terminal 176 | sha256: "51d771ef5e8e15d739be6a235dad71132ec9397ef8fe3285a5570e66e699052b" 177 | url: "https://pub.dev" 178 | source: hosted 179 | version: "5.0.0" 180 | equatable: 181 | dependency: transitive 182 | description: 183 | name: equatable 184 | sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 185 | url: "https://pub.dev" 186 | source: hosted 187 | version: "2.0.5" 188 | ffi: 189 | dependency: transitive 190 | description: 191 | name: ffi 192 | sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" 193 | url: "https://pub.dev" 194 | source: hosted 195 | version: "2.1.2" 196 | file: 197 | dependency: transitive 198 | description: 199 | name: file 200 | sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" 201 | url: "https://pub.dev" 202 | source: hosted 203 | version: "7.0.0" 204 | fixnum: 205 | dependency: transitive 206 | description: 207 | name: fixnum 208 | sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" 209 | url: "https://pub.dev" 210 | source: hosted 211 | version: "1.1.0" 212 | functional_data: 213 | dependency: transitive 214 | description: 215 | name: functional_data 216 | sha256: "76d17dc707c40e552014f5a49c0afcc3f1e3f05e800cd6b7872940bfe41a5039" 217 | url: "https://pub.dev" 218 | source: hosted 219 | version: "1.2.0" 220 | glob: 221 | dependency: transitive 222 | description: 223 | name: glob 224 | sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" 225 | url: "https://pub.dev" 226 | source: hosted 227 | version: "2.1.2" 228 | globbing: 229 | dependency: transitive 230 | description: 231 | name: globbing 232 | sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" 233 | url: "https://pub.dev" 234 | source: hosted 235 | version: "1.0.0" 236 | graphs: 237 | dependency: transitive 238 | description: 239 | name: graphs 240 | sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" 241 | url: "https://pub.dev" 242 | source: hosted 243 | version: "2.3.2" 244 | http: 245 | dependency: transitive 246 | description: 247 | name: http 248 | sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 249 | url: "https://pub.dev" 250 | source: hosted 251 | version: "1.2.2" 252 | http_parser: 253 | dependency: transitive 254 | description: 255 | name: http_parser 256 | sha256: "40f592dd352890c3b60fec1b68e786cefb9603e05ff303dbc4dda49b304ecdf4" 257 | url: "https://pub.dev" 258 | source: hosted 259 | version: "4.1.0" 260 | ini: 261 | dependency: transitive 262 | description: 263 | name: ini 264 | sha256: "12a76c53591ffdf86d1265be3f986888a6dfeb34a85957774bc65912d989a173" 265 | url: "https://pub.dev" 266 | source: hosted 267 | version: "2.1.0" 268 | intl: 269 | dependency: transitive 270 | description: 271 | name: intl 272 | sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf 273 | url: "https://pub.dev" 274 | source: hosted 275 | version: "0.19.0" 276 | io: 277 | dependency: transitive 278 | description: 279 | name: io 280 | sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" 281 | url: "https://pub.dev" 282 | source: hosted 283 | version: "1.0.4" 284 | json2yaml: 285 | dependency: transitive 286 | description: 287 | name: json2yaml 288 | sha256: da94630fbc56079426fdd167ae58373286f603371075b69bf46d848d63ba3e51 289 | url: "https://pub.dev" 290 | source: hosted 291 | version: "3.0.1" 292 | json_annotation: 293 | dependency: transitive 294 | description: 295 | name: json_annotation 296 | sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" 297 | url: "https://pub.dev" 298 | source: hosted 299 | version: "4.9.0" 300 | lists: 301 | dependency: transitive 302 | description: 303 | name: lists 304 | sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" 305 | url: "https://pub.dev" 306 | source: hosted 307 | version: "1.0.1" 308 | logging: 309 | dependency: transitive 310 | description: 311 | name: logging 312 | sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" 313 | url: "https://pub.dev" 314 | source: hosted 315 | version: "1.2.0" 316 | matcher: 317 | dependency: transitive 318 | description: 319 | name: matcher 320 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 321 | url: "https://pub.dev" 322 | source: hosted 323 | version: "0.12.16+1" 324 | melos: 325 | dependency: "direct dev" 326 | description: 327 | name: melos 328 | sha256: a3f06ed871e0348cb99909ad5ddf5f8b53cc61d894c302b5417d2db1ee7ec381 329 | url: "https://pub.dev" 330 | source: hosted 331 | version: "6.1.0" 332 | meta: 333 | dependency: transitive 334 | description: 335 | name: meta 336 | sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 337 | url: "https://pub.dev" 338 | source: hosted 339 | version: "1.15.0" 340 | mime: 341 | dependency: transitive 342 | description: 343 | name: mime 344 | sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" 345 | url: "https://pub.dev" 346 | source: hosted 347 | version: "1.0.5" 348 | mustache_template: 349 | dependency: transitive 350 | description: 351 | name: mustache_template 352 | sha256: a46e26f91445bfb0b60519be280555b06792460b27b19e2b19ad5b9740df5d1c 353 | url: "https://pub.dev" 354 | source: hosted 355 | version: "2.0.0" 356 | native_synchronization_temp: 357 | dependency: transitive 358 | description: 359 | name: native_synchronization_temp 360 | sha256: "95ccdee4c0ab7440e7d86ef76af63013cc0c379485d5e0339a7b59de6e58091e" 361 | url: "https://pub.dev" 362 | source: hosted 363 | version: "0.4.0" 364 | path: 365 | dependency: transitive 366 | description: 367 | name: path 368 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 369 | url: "https://pub.dev" 370 | source: hosted 371 | version: "1.9.0" 372 | platform: 373 | dependency: transitive 374 | description: 375 | name: platform 376 | sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" 377 | url: "https://pub.dev" 378 | source: hosted 379 | version: "3.1.5" 380 | pool: 381 | dependency: transitive 382 | description: 383 | name: pool 384 | sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" 385 | url: "https://pub.dev" 386 | source: hosted 387 | version: "1.5.1" 388 | posix: 389 | dependency: transitive 390 | description: 391 | name: posix 392 | sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a 393 | url: "https://pub.dev" 394 | source: hosted 395 | version: "6.0.1" 396 | process: 397 | dependency: transitive 398 | description: 399 | name: process 400 | sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" 401 | url: "https://pub.dev" 402 | source: hosted 403 | version: "5.0.2" 404 | prompts: 405 | dependency: transitive 406 | description: 407 | name: prompts 408 | sha256: "3773b845e85a849f01e793c4fc18a45d52d7783b4cb6c0569fad19f9d0a774a1" 409 | url: "https://pub.dev" 410 | source: hosted 411 | version: "2.0.0" 412 | pub_semver: 413 | dependency: transitive 414 | description: 415 | name: pub_semver 416 | sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" 417 | url: "https://pub.dev" 418 | source: hosted 419 | version: "2.1.4" 420 | pub_updater: 421 | dependency: transitive 422 | description: 423 | name: pub_updater 424 | sha256: "54e8dc865349059ebe7f163d6acce7c89eb958b8047e6d6e80ce93b13d7c9e60" 425 | url: "https://pub.dev" 426 | source: hosted 427 | version: "0.4.0" 428 | pubspec: 429 | dependency: transitive 430 | description: 431 | name: pubspec 432 | sha256: f534a50a2b4d48dc3bc0ec147c8bd7c304280fff23b153f3f11803c4d49d927e 433 | url: "https://pub.dev" 434 | source: hosted 435 | version: "2.3.0" 436 | pubspec_lock: 437 | dependency: transitive 438 | description: 439 | name: pubspec_lock 440 | sha256: ed5fc1ecd0cdc0e14475a091afcb2c4cbb00e74cebff17635e9abbec18d76cc4 441 | url: "https://pub.dev" 442 | source: hosted 443 | version: "3.0.2" 444 | pubspec_manager: 445 | dependency: transitive 446 | description: 447 | name: pubspec_manager 448 | sha256: b2674161f3f69ed07bc164dc4172afc190d56f060a293a8eb6fa691e5ddf9b5c 449 | url: "https://pub.dev" 450 | source: hosted 451 | version: "1.0.0" 452 | quiver: 453 | dependency: transitive 454 | description: 455 | name: quiver 456 | sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 457 | url: "https://pub.dev" 458 | source: hosted 459 | version: "3.2.1" 460 | scope: 461 | dependency: transitive 462 | description: 463 | name: scope 464 | sha256: "9930a3822bd33d1884a642d1cd79e6baf56d17288b3e0c54ae7c00cb559ef614" 465 | url: "https://pub.dev" 466 | source: hosted 467 | version: "4.1.1" 468 | settings_yaml: 469 | dependency: transitive 470 | description: 471 | name: settings_yaml 472 | sha256: ed2714686a1a22d45c1454ca3da1b0ce889b639b929aa09f6afa2bba8c0a423e 473 | url: "https://pub.dev" 474 | source: hosted 475 | version: "8.2.0" 476 | source_span: 477 | dependency: transitive 478 | description: 479 | name: source_span 480 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 481 | url: "https://pub.dev" 482 | source: hosted 483 | version: "1.10.0" 484 | sprintf: 485 | dependency: transitive 486 | description: 487 | name: sprintf 488 | sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" 489 | url: "https://pub.dev" 490 | source: hosted 491 | version: "7.0.0" 492 | stack_trace: 493 | dependency: transitive 494 | description: 495 | name: stack_trace 496 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 497 | url: "https://pub.dev" 498 | source: hosted 499 | version: "1.11.1" 500 | stream_channel: 501 | dependency: transitive 502 | description: 503 | name: stream_channel 504 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 505 | url: "https://pub.dev" 506 | source: hosted 507 | version: "2.1.2" 508 | string_scanner: 509 | dependency: transitive 510 | description: 511 | name: string_scanner 512 | sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" 513 | url: "https://pub.dev" 514 | source: hosted 515 | version: "1.3.0" 516 | strings: 517 | dependency: transitive 518 | description: 519 | name: strings 520 | sha256: "052836499f03897d3860a603b330c1ea3c8a14177b21f34b15a1295f36024aae" 521 | url: "https://pub.dev" 522 | source: hosted 523 | version: "3.1.2" 524 | sum_types: 525 | dependency: transitive 526 | description: 527 | name: sum_types 528 | sha256: c0a0fad9a518d011987e1d9f27fc336194294e55dafdc3699363e52aa5776e09 529 | url: "https://pub.dev" 530 | source: hosted 531 | version: "0.3.5" 532 | system_info2: 533 | dependency: transitive 534 | description: 535 | name: system_info2 536 | sha256: "65206bbef475217008b5827374767550a5420ce70a04d2d7e94d1d2253f3efc9" 537 | url: "https://pub.dev" 538 | source: hosted 539 | version: "4.0.0" 540 | term_glyph: 541 | dependency: transitive 542 | description: 543 | name: term_glyph 544 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 545 | url: "https://pub.dev" 546 | source: hosted 547 | version: "1.2.1" 548 | test_api: 549 | dependency: transitive 550 | description: 551 | name: test_api 552 | sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" 553 | url: "https://pub.dev" 554 | source: hosted 555 | version: "0.7.3" 556 | typed_data: 557 | dependency: transitive 558 | description: 559 | name: typed_data 560 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 561 | url: "https://pub.dev" 562 | source: hosted 563 | version: "1.3.2" 564 | unicode: 565 | dependency: transitive 566 | description: 567 | name: unicode 568 | sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" 569 | url: "https://pub.dev" 570 | source: hosted 571 | version: "0.3.1" 572 | uri: 573 | dependency: transitive 574 | description: 575 | name: uri 576 | sha256: "889eea21e953187c6099802b7b4cf5219ba8f3518f604a1033064d45b1b8268a" 577 | url: "https://pub.dev" 578 | source: hosted 579 | version: "1.0.0" 580 | uuid: 581 | dependency: transitive 582 | description: 583 | name: uuid 584 | sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" 585 | url: "https://pub.dev" 586 | source: hosted 587 | version: "4.4.2" 588 | validators2: 589 | dependency: transitive 590 | description: 591 | name: validators2 592 | sha256: "5c63054b2f47b6a3f39e0d0e3f5d38829db4545250144a34c9e1585466de4814" 593 | url: "https://pub.dev" 594 | source: hosted 595 | version: "5.0.0" 596 | web: 597 | dependency: transitive 598 | description: 599 | name: web 600 | sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 601 | url: "https://pub.dev" 602 | source: hosted 603 | version: "1.0.0" 604 | win32: 605 | dependency: transitive 606 | description: 607 | name: win32 608 | sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" 609 | url: "https://pub.dev" 610 | source: hosted 611 | version: "5.5.3" 612 | yaml: 613 | dependency: transitive 614 | description: 615 | name: yaml 616 | sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" 617 | url: "https://pub.dev" 618 | source: hosted 619 | version: "3.1.2" 620 | yaml_edit: 621 | dependency: transitive 622 | description: 623 | name: yaml_edit 624 | sha256: e9c1a3543d2da0db3e90270dbb1e4eebc985ee5e3ffe468d83224472b2194a5f 625 | url: "https://pub.dev" 626 | source: hosted 627 | version: "2.2.1" 628 | sdks: 629 | dart: ">=3.4.4 <4.0.0" 630 | --------------------------------------------------------------------------------