Skip to content

Fix/auth mode bug #4944

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
18d89a0
chore(aft): Added generate amplify-swift (#4630)
Equartey Apr 8, 2024
05bfb45
chore(datastore): Stubbed Swift migration (#4685)
Equartey Apr 12, 2024
8453563
chore(datastore): stub pigeon for api bridge (#4837)
Equartey May 7, 2024
8184b73
chore(datastore): add subscribe() impl (#4846)
Equartey May 13, 2024
2c16e75
chore(datastore): add query & mutate impl (#4858)
Equartey May 15, 2024
1849b87
test(swift-datastore): add unit tests for GraphQLResposne decoding lo…
5d May 15, 2024
705f503
chore(datastore): DataStore Cocoa Pod removed modules (#4934)
Equartey May 29, 2024
9269cea
test(swift): add unit test cases for extension functions (#4894)
5d May 29, 2024
699e2e8
Chore(datastore): migrate cognito plugin (#4913)
khatruong2009 May 29, 2024
c8ee3cf
chore(datastore): Regenerate Amplify Swift Plugins (#4941)
Equartey May 30, 2024
f9f4094
wip: fix add auth mode to req
Equartey May 30, 2024
2d42f5e
temp model changes for sample app
Equartey May 30, 2024
a2e38fb
fix: corrected enum converter
Equartey May 31, 2024
758a335
fix(datastore): pass auth mode from swift
Equartey May 31, 2024
a99d900
chore: removed authMode check as it will always be nil
Equartey May 31, 2024
9a8062f
fix: add modelName to decoding logic
Equartey May 31, 2024
da85f66
chore: made modelName for decode logic required
Equartey May 31, 2024
e6c95e1
fix: added null guards
Equartey May 31, 2024
9682b52
fix: subscription data event
Equartey May 31, 2024
0938618
revert modelName requirement changes
Equartey May 31, 2024
5fac126
remove guard check
Equartey May 31, 2024
15ec356
fix(datastore): keep swift graphql decoding with non optional modelNa…
5d May 31, 2024
f53ab59
fix: reuse sendErrorEvent helper
Equartey May 31, 2024
4b449ca
fix(datastore): crash when insert cancellables (#4956)
5d May 31, 2024
8aa7b26
stash
5d Jun 1, 2024
7fd3946
Merge branch '5d/fix-error-handling' into fix/auth-mode-bug
Equartey Jun 1, 2024
bacae6d
test models
Equartey Jun 1, 2024
0c42e94
fix(datastore): reclassify unauthorized error
5d Jun 1, 2024
6bc6afd
fix: consolidated NativeGraphQLResponse to one payload to match AppSync
Equartey Jun 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
## Platform files generated by Flutter during `flutter create`
**/example/android/** linguist-generated
**/example/ios/** linguist-generated
**/example/ios/unit_tests/** linguist-generated=false
**/example/linux/** linguist-generated
**/example/macos/** linguist-generated
**/example/windows/** linguist-generated
Expand All @@ -71,6 +72,9 @@
## Generated SDK files
packages/**/lib/src/sdk/src/** linguist-generated

## Generated Swift Plugins
packages/amplify_datastore/ios/internal/** linguist-generated

## Smithy files
packages/smithy/goldens/lib/** linguist-generated
packages/smithy/goldens/lib2/** linguist-generated
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import 'dart:async';
import 'dart:io';

import 'package:aft/aft.dart';
import 'package:aft/src/options/glob_options.dart';
import 'package:async/async.dart';
import 'package:git/git.dart';
import 'package:io/io.dart';
import 'package:path/path.dart' as p;

class PluginConfig {
const PluginConfig({
required this.name,
required this.remotePathToSource,
});

/// The name of the plugin.
final String name;

/// The path to the plugin source files in the Amplify Swift repo.
final String remotePathToSource;
}

/// Command for generating the Amplify Swift plugins for the DataStore plugin.
class GenerateAmplifySwiftCommand extends AmplifyCommand with GlobOptions {
GenerateAmplifySwiftCommand() {
argParser
..addOption(
'branch',
abbr: 'b',
help: 'The branch of Amplify Swift to target',
defaultsTo: 'release',
)
..addFlag(
'diff',
abbr: 'd',
help: 'Show the diff of the generated files',
negatable: false,
defaultsTo: false,
);
}

@override
String get description =>
'Generates Amplify Swift DataStore for the DataStore plugin.';

@override
String get name => 'amplify-swift';

@override
bool get hidden => true;

/// The branch of Amplify Swift to target.
///
/// If not provided, defaults to `release`.
late final branchTarget = argResults!['branch'] as String;

late final _dataStoreRootDir =
p.join(rootDir.path, 'packages/amplify_datastore');

final _pluginOutputDir = 'ios/internal';
final _exampleOutputDir = 'example/ios';

/// Whether to check the diff of the generated files.
/// If not provided, defaults to `false`.
late final isDiff = argResults!['diff'] as bool;

/// Cache of repos by git ref.
final _repoCache = <String, Directory>{};
final _cloneMemo = AsyncMemoizer<Directory>();

final _amplifySwiftPlugins = [
const PluginConfig(
name: 'AWSDataStorePlugin',
remotePathToSource: 'AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin',
),
const PluginConfig(
name: 'AWSPluginsCore',
remotePathToSource: 'AmplifyPlugins/Core/AWSPluginsCore',
),
const PluginConfig(
name: 'Amplify',
remotePathToSource: 'Amplify',
),
];

final _importsToRemove = [
'import Amplify',
'import AWSPluginsCore',
'import AWSDataStorePlugin',
];

/// Downloads Amplify Swift from GitHub into a temporary directory.
Future<Directory> _downloadRepository() => _cloneMemo.runOnce(() async {
final cloneDir =
await Directory.systemTemp.createTemp('amplify_swift_');
logger
..info('Downloading Amplify Swift...')
..verbose('Cloning repo to ${cloneDir.path}');
await runGit(
[
'clone',
// https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/
'--filter=tree:0',
'https://github.com/aws-amplify/amplify-swift.git',
cloneDir.path,
],
echoOutput: verbose,
);
logger.info('Successfully cloned Amplify Swift Repo');
return cloneDir;
});

/// Checks out [ref] in [pluginDir].
Future<Directory> _checkoutRepositoryRef(
Directory pluginDir,
String ref,
) async {
logger
..info('Checking out target branch: $ref')
..verbose('Creating git work tree in $pluginDir');
final worktreeDir =
await Directory.systemTemp.createTemp('amplify_swift_worktree_');
try {
await runGit(
['worktree', 'add', worktreeDir.path, ref],
processWorkingDir: pluginDir.path,
);
} on Exception catch (e) {
if (e.toString().contains('already checked out')) {
return pluginDir;
}
rethrow;
}
return worktreeDir;
}

/// Find and replaces the `import` statements in the plugin files.
Future<void> _replaceImports(Directory pluginDir) async {
final files = await pluginDir.list(recursive: true).toList();
for (final file in files) {
if (file is! File) {
continue;
}
// Only process Swift files.
if (!file.path.endsWith('.swift')) {
continue;
}
final contents = await file.readAsString();
// remove the list of import statement for Amplify including line breaks
final newContents = contents.split('\n').where((line) {
return !_importsToRemove.any((import) => line.contains(import));
}).join('\n');
await file.writeAsString(newContents);
}
}

/// Remove `info.plist` from the plugin files.
Future<void> _removePListFiles(Directory pluginDir) async {
final files = await pluginDir.list(recursive: true).toList();
for (final file in files) {
if (file is! File) {
continue;
}
// Only process Info.plist files.
if (!file.path.endsWith('Info.plist')) {
continue;
}
await file.delete();
}
}

/// Transforms the plugin files to Amplify Flutter requirements.
Future<void> _transformPlugin(Directory directory) async {
logger
..info('Transforming plugin files...')
..verbose('In ${directory.path}');
await _replaceImports(directory);
await _removePListFiles(directory);
}

/// Sets up the Amplify Swift repo for use later
Future<void> _setupRepo() async {
if (_repoCache[branchTarget] != null) {
return;
}
final repoDir = await _downloadRepository();
final repoRef = await _checkoutRepositoryRef(repoDir, branchTarget);

_repoCache[branchTarget] = repoRef;
}

/// Returns the directory for the plugin at [path].
Future<Directory> _pluginDirForPath(String path) async {
final repoDir = _repoCache[branchTarget];
if (repoDir == null) {
exitError('No cached repo for branch $branchTarget');
}

final pluginDir = Directory.fromUri(
repoDir.uri.resolve(path),
);

await _transformPlugin(pluginDir);

return pluginDir;
}

/// Generates the Amplify Swift plugin for [plugin].
Future<void> _generatePlugin(PluginConfig plugin) async {
logger.info('Selecting source files for ${plugin.name}...');

// The directory in the Amplify Swift repo where the plugin source files are.
final remotePluginDir = await _pluginDirForPath(plugin.remotePathToSource);

// The local directory to copy the plugin files to.
final outputDir = Directory(
p.join(_dataStoreRootDir, _pluginOutputDir, plugin.name),
);

// Clear out the directory if it already exists.
// This is to ensure that we don't have any stale files.
if (await outputDir.exists()) {
logger.info(
'Deleting existing plugin directory for ${plugin.name}...',
);
await outputDir.delete(recursive: true);
}
await outputDir.create(recursive: true);

// Copy the files from the repo to the plugin directory.
logger
..info('Copying plugin files for ${plugin.name}...')
..verbose('From $remotePluginDir to $outputDir');
await copyPath(remotePluginDir.path, outputDir.path);
}

Future<void> checkDiff(PluginConfig plugin) async {
logger.info('Checking diff for ${plugin.name}...');
final incoming = (await _pluginDirForPath(plugin.remotePathToSource)).path;
final current = p.join(_dataStoreRootDir, _pluginOutputDir, plugin.name);
final diffCmd = await Process.start(
'git',
[
'diff',
'--no-index',
'--exit-code',
incoming,
current,
],
mode: verbose ? ProcessStartMode.inheritStdio : ProcessStartMode.normal,
);
final exitCode = await diffCmd.exitCode;
if (exitCode != 0) {
exitError(
'`diff` failed: $exitCode. There are differences between $incoming and $current',
);
}
logger.info(
'No differences between incoming and current for ${plugin.name}.',
);
}

/// Runs pod install after copying files to the plugin directory.
Future<void> _podInstall() async {
final podFilePath = p.join(_dataStoreRootDir, _exampleOutputDir);
logger.verbose('Running pod install in $podFilePath...');

final podInstallCmd = await Process.start(
'pod',
[
'install',
],
mode: verbose ? ProcessStartMode.inheritStdio : ProcessStartMode.normal,
workingDirectory: podFilePath,
);
final exitCode = await podInstallCmd.exitCode;
if (exitCode != 0) {
exitError('`pod install` failed: $exitCode.');
}
}

Future<void> _runDiff() async {
await _setupRepo();
for (final plugin in _amplifySwiftPlugins) {
await checkDiff(plugin);
}
logger.info(
'Successfully checked diff for Amplify Swift plugins',
);
}

Future<void> _runGenerate() async {
await _setupRepo();
for (final plugin in _amplifySwiftPlugins) {
await _generatePlugin(plugin);
}
await _podInstall();
logger.info('Successfully generated Amplify Swift plugins');
}

@override
Future<void> run() async {
logger.info('Generating Amplify Swift plugins.');
await super.run();
switch (isDiff) {
case true:
await _runDiff();
default:
await _runGenerate();
break;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import 'package:aft/aft.dart';
import 'package:aft/src/commands/generate/generate_amplify_swift_command.dart';
import 'package:aft/src/commands/generate/generate_goldens_command.dart';
import 'package:aft/src/commands/generate/generate_sdk_command.dart';
import 'package:aft/src/commands/generate/generate_workflows_command.dart';
Expand All @@ -12,6 +13,7 @@ class GenerateCommand extends AmplifyCommand {
addSubcommand(GenerateSdkCommand());
addSubcommand(GenerateWorkflowsCommand());
addSubcommand(GenerateGoldensCommand());
addSubcommand(GenerateAmplifySwiftCommand());
}

@override
Expand Down
1 change: 1 addition & 0 deletions packages/aft/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies:
git: any # override
glob: ^2.1.0
graphs: ^2.1.0
io: ^1.0.4
json_annotation: ">=4.8.1 <4.9.0"
markdown: ^5.0.0
mason: ^0.1.0-dev.40
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.amazonaws.amplify.amplify_datastore.pigeons.NativeApiPlugin
import com.amazonaws.amplify.amplify_datastore.pigeons.NativeAuthBridge
import com.amazonaws.amplify.amplify_datastore.pigeons.NativeAuthPlugin
import com.amazonaws.amplify.amplify_datastore.pigeons.NativeAuthUser
import com.amazonaws.amplify.amplify_datastore.pigeons.NativeGraphQLSubscriptionResponse
import com.amazonaws.amplify.amplify_datastore.types.model.FlutterCustomTypeSchema
import com.amazonaws.amplify.amplify_datastore.types.model.FlutterModelSchema
import com.amazonaws.amplify.amplify_datastore.types.model.FlutterSerializedModel
Expand Down Expand Up @@ -920,6 +921,13 @@ class AmplifyDataStorePlugin :
callback(kotlin.Result.failure(e))
}
}

override fun sendSubscriptionEvent(
event: NativeGraphQLSubscriptionResponse,
callback: (kotlin.Result<Unit>) -> Unit
) {
throw NotImplementedError("Not yet implemented")
}

override fun configure(
version: String,
Expand Down
Loading
Loading