Skip to content
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

feat: update list API #4600

Merged
merged 17 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class StorageCategory extends AmplifyCategory<StoragePluginInterface> {
/// returns a [StorageListOperation].
/// {@endtemplate}
StorageListOperation list({
String? path,
required StoragePath path,
StorageListOptions? options,
}) {
return identifyCall(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ abstract class StoragePluginInterface extends AmplifyPluginInterface {

/// {@macro amplify_core.amplify_storage_category.list}
StorageListOperation list({
String? path,
required StoragePath path,
StorageListOptions? options,
}) {
throw UnimplementedError('list() has not been implemented.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class StorageListOptions extends StorageOperationOptions
AWSDebuggable {
/// {@macro amplify_core.storage.list_options}
const StorageListOptions({
super.accessLevel,
this.pageSize = 1000,
this.nextToken,
this.pluginOptions,
Expand All @@ -30,14 +29,13 @@ class StorageListOptions extends StorageOperationOptions
final StorageListPluginOptions? pluginOptions;

@override
List<Object?> get props => [accessLevel, pageSize, nextToken, pluginOptions];
List<Object?> get props => [pageSize, nextToken, pluginOptions];

@override
String get runtimeTypeName => 'StorageListOptions';

@override
Map<String, Object?> toJson() => {
'accessLevel': accessLevel?.name,
'pageSize': pageSize,
'nextToken': nextToken,
'pluginOptions': pluginOptions?.toJson(),
Expand Down
4 changes: 2 additions & 2 deletions packages/amplify_core/lib/src/types/storage/list_request.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import 'package:amplify_core/amplify_core.dart';
class StorageListRequest {
/// {@macro amplify_core.storage.list_request}
const StorageListRequest({
this.path,
required this.path,
khatruong2009 marked this conversation as resolved.
Show resolved Hide resolved
this.options,
});

/// Path to list objects under.
final String? path;
final StoragePath path;

/// Configurable options of the [StorageListRequest].
final StorageListOptions? options;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@
class StorageItem {
/// {@macro amplify_core.storage.storage_item}
const StorageItem({
this.key,
// TODO(Jordan-Nelson): make required
this.path = '',
required this.path,
this.size,
this.lastModified,
this.eTag,
this.metadata = const <String, String>{},
});

// TODO(Jordan-Nelson): Remove key
final String? key;
final String path;
final int? size;
final DateTime? lastModified;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ void main() {
),
).result;

expect(result.copiedItem.key, testObject3CopyKey);
expect(result.copiedItem.path, testObject3CopyKey);
expect(result.copiedItem.eTag, isNotEmpty);
});

Expand Down Expand Up @@ -683,7 +683,6 @@ void main() {
(WidgetTester tester) async {
const filesToUpload = 2;
const filesToList = 1;
const accessLevel = StorageAccessLevel.private;
final uploadedKeys = <String>[];
// Upload some files to test.
for (var i = filesToUpload; i > 0; i--) {
Expand All @@ -706,8 +705,10 @@ void main() {

// Call list() and ensure length of result matches pageSize.
final listResult = await Amplify.Storage.list(
path: StoragePath.withIdentityId(
(identityId) => 'private/$identityId/',
),
options: const StorageListOptions(
accessLevel: accessLevel,
pageSize: filesToList,
),
).result;
Expand All @@ -729,7 +730,6 @@ void main() {
(WidgetTester tester) async {
const filesToUpload = 2;
const filesToList = 1;
const accessLevel = StorageAccessLevel.private;
final keyPrefix = 'testObjectList${uuid()}';
final uploadedKeys = <String>[];
// Upload some files to test.
Expand Down Expand Up @@ -758,12 +758,13 @@ void main() {
do {
// Call list() until nextToken is null and ensure we paginated expected times.
final listResult = await Amplify.Storage.list(
path: StoragePath.withIdentityId(
(identityId) => 'private/$identityId/',
),
options: StorageListOptions(
accessLevel: accessLevel,
pageSize: filesToList,
nextToken: lastNextToken,
),
path: keyPrefix,
).result;
lastNextToken = listResult.nextToken;
timesCalled++;
Expand Down
2 changes: 1 addition & 1 deletion packages/storage/amplify_storage_s3/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ class _HomeScreenState extends State<HomeScreen> {
Future<void> _listAllPublicFiles() async {
try {
final result = await Amplify.Storage.list(
path: const StoragePath.fromString('public'),
options: const StorageListOptions(
accessLevel: StorageAccessLevel.guest,
pluginOptions: S3ListPluginOptions.listAll(),
),
).result;
Expand Down
26 changes: 10 additions & 16 deletions packages/storage/amplify_storage_s3_dart/example/bin/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,26 +76,21 @@ Future<void> main() async {

Future<void> listOperation() async {
final path = prompt('Enter a path to list objects for: ');
final accessLevel = promptStorageAccessLevel(
'Choose the storage access level associated with the path: ',
);
final listAll = prompt('List with pagination? (Y/n): ').toLowerCase() == 'n';

const pageSize = 5;

// get plugin with plugin key to gain S3 specific interface
final s3Plugin = Amplify.Storage.getPlugin(AmplifyStorageS3Dart.pluginKey);
final options = listAll
? StorageListOptions(
accessLevel: accessLevel,
pluginOptions: const S3ListPluginOptions.listAll(),
? const StorageListOptions(
pluginOptions: S3ListPluginOptions.listAll(),
)
: StorageListOptions(
accessLevel: accessLevel,
: const StorageListOptions(
pageSize: pageSize,
);
final operation = s3Plugin.list(
path: path,
path: StoragePath.fromString(path),
options: options,
);

Expand All @@ -116,7 +111,7 @@ Future<void> listOperation() async {
stdout.writeln('Listed ${result.items.length} objects.');
stdout.writeln('Sub directories: ${result.metadata.subPaths}');
result.items.asMap().forEach((index, item) {
stdout.writeln('$index. key: ${item.key} | size: ${item.size}');
stdout.writeln('$index. path: ${item.path} | size: ${item.size}');
});

if (!result.hasNextPage) {
Expand All @@ -133,9 +128,8 @@ Future<void> listOperation() async {

result = await s3Plugin
.list(
path: path,
path: StoragePath.fromString(path),
options: StorageListOptions(
accessLevel: accessLevel,
pageSize: pageSize,
nextToken: result.nextToken,
),
Expand All @@ -155,7 +149,7 @@ Future<void> getPropertiesOperation() async {

stdout
..writeln('Got properties: ')
..writeln('key: ${result.storageItem.key}')
..writeln('path: ${result.storageItem.path}')
..writeln('size: ${result.storageItem.size}')
..writeln('lastModified: ${result.storageItem.lastModified}')
..writeln('eTag: ${result.storageItem.eTag}')
Expand Down Expand Up @@ -289,7 +283,7 @@ Future<void> uploadDataUrlOperation() async {
final result = await uploadDataOperation.result;
stdout
..writeln('Uploaded data url: ')
..writeln('key: ${result.uploadedItem.key}')
..writeln('path: ${result.uploadedItem.path}')
..writeln('size: ${result.uploadedItem.size}')
..writeln('lastModified: ${result.uploadedItem.lastModified}')
..writeln('eTag: ${result.uploadedItem.eTag}');
Expand Down Expand Up @@ -367,7 +361,7 @@ Future<void> copyOperation() async {
final result = await copyOperation.result;
stdout
..writeln('Copied object: ')
..writeln('key: ${result.copiedItem.key}')
..writeln('path: ${result.copiedItem.path}')
..writeln('size: ${result.copiedItem.size}')
..writeln('lastModified: ${result.copiedItem.lastModified}')
..writeln('eTag: ${result.copiedItem.eTag}')
Expand All @@ -391,7 +385,7 @@ Future<void> removeOperation() async {
final result = await removeOperation.result;
stdout
..writeln('Remove completed.')
..writeln('Removed object: ${result.removedItem.key}');
..writeln('Removed object: ${result.removedItem.path}');
} on Exception catch (error) {
stderr
..writeln('Something went wrong...')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ class AmplifyStorageS3Dart extends StoragePluginInterface
credentialsProvider: credentialsProvider,
s3PluginConfig: s3PluginConfig,
delimiter: _delimiter,
prefixResolver: _prefixResolver!,
pathResolver: _pathResolver,
logger: logger,
dependencyManager: dependencies,
Expand All @@ -141,15 +140,14 @@ class AmplifyStorageS3Dart extends StoragePluginInterface

@override
S3ListOperation list({
String? path,
required StoragePath path,
StorageListOptions? options,
}) {
final s3PluginOptions = reifyPluginOptions(
pluginOptions: options?.pluginOptions,
defaultPluginOptions: const S3ListPluginOptions(),
);
final s3Options = StorageListOptions(
accessLevel: options?.accessLevel,
pluginOptions: s3PluginOptions,
nextToken: options?.nextToken,
pageSize: options?.pageSize ?? 1000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ class S3Item extends StorageItem
AWSDebuggable {
/// {@macro storage.amplify_storage_s3.storage_s3_item}
S3Item({
super.key,
// TODO(Jordan-Nelson): make required
super.path,
required super.path,
super.size,
super.lastModified,
super.eTag,
Expand All @@ -35,7 +33,6 @@ class S3Item extends StorageItem
return storageItem is S3Item
? storageItem
: S3Item(
key: storageItem.key,
path: storageItem.path,
size: storageItem.size,
lastModified: storageItem.lastModified,
Expand All @@ -50,9 +47,8 @@ class S3Item extends StorageItem
/// Creates a [S3Item] from [s3.S3Object] provided by S3 Client.
@internal
factory S3Item.fromS3Object(
s3.S3Object object, {
required String prefixToDrop,
}) {
s3.S3Object object,
) {
final key = object.key;

// Sanity check, key property should never be null in a S3Object returned
Expand All @@ -64,13 +60,7 @@ class S3Item extends StorageItem
);
}

final keyDroppedPrefix = dropPrefixFromKey(
prefixToDrop: prefixToDrop,
key: key,
);

return S3Item(
key: keyDroppedPrefix,
path: key,
size: object.size?.toInt(),
lastModified: object.lastModified,
Expand All @@ -83,12 +73,9 @@ class S3Item extends StorageItem
@internal
factory S3Item.fromHeadObjectOutput(
s3.HeadObjectOutput headObjectOutput, {
// TODO(Jordan-Nelson): remove key
String? key,
required String path,
}) {
return S3Item(
key: key,
path: path,
lastModified: headObjectOutput.lastModified,
eTag: headObjectOutput.eTag,
Expand All @@ -104,12 +91,9 @@ class S3Item extends StorageItem
@internal
factory S3Item.fromGetObjectOutput(
s3.GetObjectOutput getObjectOutput, {
// TODO(Jordan-Nelson): remove key
String? key,
required String path,
}) {
return S3Item(
key: key,
path: path,
lastModified: getObjectOutput.lastModified,
eTag: getObjectOutput.eTag,
Expand All @@ -120,15 +104,6 @@ class S3Item extends StorageItem
);
}

/// Removes [prefixToDrop] from [key] string.
@internal
static String dropPrefixFromKey({
required String prefixToDrop,
required String key,
}) {
return key.replaceRange(0, prefixToDrop.length, '');
}

/// Object `versionId`, may be available when S3 bucket versioning is enabled.
final String? versionId;

Expand All @@ -137,7 +112,6 @@ class S3Item extends StorageItem

@override
List<Object?> get props => [
key,
path,
size,
lastModified,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.