Skip to content

Commit

Permalink
feat: v1 improvements (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
HomelessDinosaur authored Mar 12, 2024
1 parent 34b574f commit bf93fd0
Show file tree
Hide file tree
Showing 85 changed files with 3,717 additions and 1,513 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ jobs:
build:
uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/dart_package.yml@v1
with:
coverage_excludes: "*.pb*.dart"
coverage_excludes: "**/*.pb*.dart"
min_coverage: 0
61 changes: 21 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ To create our Nitric project, we have to create a `nitric.yaml` file. The handle
name: my_profile_api
services:
- match: bin/my_profile_api.dart
start: dart run bin/my_profile_api.dart
start: dart run $SERVICE_PATH
```
## Create a Profile class
Expand Down Expand Up @@ -141,34 +141,34 @@ class Profile {
Applications built with Nitric can contain many APIs, let's start by adding one to this project to serve as the public endpoint. Rename `bin/my_profile_api.dart` to `bin/profiles.dart`

```dart
import 'package:uuid/uuid.dart';
import 'package:nitric_sdk/nitric.dart';
import 'package:nitric_sdk/resources.dart';
import 'package:nitric_sdk/src/context/common.dart';
import 'package:nitric_sdk/src/api/collection.dart';
import 'package:nitric_sdk/src/nitric.dart';
import 'package:nitric_sdk/src/resources/common.dart';
import 'package:uuid/uuid.dart';
void main() {
// Create an API named 'public'
final profileApi = api("public");
// Define a collection named 'profiles', then request reading and writing permissions.
final profiles = collection<Profile>("profiles").requires([
CollectionPermission.writing,
CollectionPermission.deleting,
CollectionPermission.reading
// Define a key value store named 'profiles', then request getting, setting and deleting permissions.
final profiles = store("profiles").requires([
KeyValuePermission.getting,
KeyValuePermission.setting,
KeyValuePermission.deleting
]);
}
```

Here we're creating an API named `public` and a collection named `profiles`, then requesting read, write, and delete permissions which allows our function to access the collection.
Here we're creating an API named `public` and a key value store named `profiles`, then requesting get, set, and delete permissions which allows our function to access the key value store.

<Note>
Resources in Nitric like `api` and `collection` represent high-level cloud
Resources in Nitric like `api` and `key value store` represent high-level cloud
resources. When your app is deployed Nitric automatically converts these
requests into appropriate resources for the specific
[provider](https://nitric.io/docs/reference/providers). Nitric also takes care of adding the IAM
roles, policies, etc. that grant the requested access. For example the
`collection` resource uses DynamoDB in AWS or FireStore on Google Cloud.
`key value stores` resource uses DynamoDB in AWS or FireStore on Google Cloud.
</Note>

### Create profiles with POST
Expand All @@ -189,7 +189,7 @@ profileApi.post("/profiles", (ctx) async {
final profile = Profile.fromJson(ctx.req.json());
// Store the new profile in the profiles collection
await profiles.key(id).put(profile);
await profiles.set(id, profile);
// Send a success response.
ctx.resp.body = "Profile $id created.";
Expand All @@ -206,9 +206,9 @@ profileApi.get("/profiles/:id", (ctx) async {
try {
// Retrieve and return the profile data
final profile = await profiles.key(id).access();
final profile = await profiles.get(id);
ctx.resp.json(profile.toJson());
} on KeyNotFoundException catch (e) {
} on Exception catch (e) {
print(e);
ctx.resp.status = 404;
ctx.resp.body = "Profile $id not found.";
Expand All @@ -218,19 +218,6 @@ profileApi.get("/profiles/:id", (ctx) async {
});
```

### List all profiles with GET

```dart
profileApi.get("/profiles", (ctx) async {
// Return all profiles
final allProfiles = await profiles.list();
ctx.resp.json({'profiles': allProfiles});
return ctx;
});
```

### Remove a profile with DELETE

```dart
Expand All @@ -239,11 +226,11 @@ profileApi.delete("/profiles/:id", (ctx) async {
// Delete the profile
try {
await profiles.key(id).unset();
await profiles.delete(id);
ctx.resp.body = "Profile $id removed.";
} on KeyNotFoundException catch (e) {
} on Exception catch (e) {
ctx.resp.status = 404;
ctx.resp.body = "Profile $id not found.";
ctx.resp.body = "Profile $id not found. $e";
}
return ctx;
Expand All @@ -255,15 +242,9 @@ profileApi.delete("/profiles/:id", (ctx) async {
Now that you have an API defined with handlers for each of its methods, it's time to test it locally.

```bash
npm run dev
nitric start
```

<Note>
the `dev` script starts the Nitric Server using `nitric start`, which provides
local interfaces to emulate cloud resources, then runs your functions and
allows them to connect.
</Note>

Once it starts, the application will receive requests via the API port. You can use the Local Dashboard or any HTTP client to test the API. We'll keep it running for our tests. If you want to update your functions, just save them, they'll be reloaded automatically.

## Test the API
Expand Down Expand Up @@ -354,7 +335,7 @@ If you want to go a bit deeper and create some other resources with Nitric, why
Define a bucket named `profilesImg` with reading/writing permissions.

```dart
final profilesImg = bucket("profilesImg").requires([BucketPermission.reading, BucketPermission.writing]);
final profilesImg = Nitric.bucket("profilesImg").requires([BucketPermission.reading, BucketPermission.writing]);
```

### Get a URL to upload a profile image
Expand Down
56 changes: 30 additions & 26 deletions example/services/nitric_example.dart
Original file line number Diff line number Diff line change
@@ -1,33 +1,39 @@
import 'package:nitric_sdk/nitric.dart';
import 'package:nitric_sdk/resources.dart';
import 'package:nitric_sdk/src/context/common.dart';
import 'package:uuid/uuid.dart';

class Profile {
String name;
int age;
String homeTown;
late String name;
late int age;
late String homeTown;
late List<String> contacts;

Profile(this.name, this.age, this.homeTown);
Profile({required this.name, required this.age, required this.homeTown});

Profile.fromJson(Map<String, dynamic> contents)
: name = contents["name"] as String,
age = contents["age"] as int,
homeTown = contents["homeTown"] as String;
homeTown = contents["homeTown"] as String,
contacts = List<String>.from(contents["contacts"]);

Map<String, dynamic> toJson() => {
'name': name,
'age': age,
'homeTown': homeTown,
};
Map<String, dynamic> toJson() =>
{'name': name, 'age': age, 'homeTown': homeTown, 'contacts': contacts};
}

void main() {
var oidc = Nitric.oidcRule(
"profile security",
"https://dev-w7gm5ldb.us.auth0.com",
["https://test-security-definition/"]);

// Create an API named 'public'
final profileApi = Nitric.api("public");
final profileApi = Nitric.api("public",
opts: ApiOptions(security: [
oidc(["user:read"])
]));

// Define a collection named 'profiles', then request reading and writing permissions.
final profiles = Nitric.store<Profile>("profiles").requires([
final profiles = Nitric.store("profiles").requires([
KeyValueStorePermission.getting,
KeyValueStorePermission.deleting,
KeyValueStorePermission.setting
Expand All @@ -36,22 +42,22 @@ void main() {
final profilesImg = Nitric.bucket("profilesImg")
.requires([BucketPermission.reading, BucketPermission.writing]);

profilesImg.on(BlobEventType.write, "*", (ctx) async {
return ctx;
});

profileApi.post("/profiles", (ctx) async {
final uuid = Uuid();

final id = uuid.v4();

final profile = Profile.fromJson(ctx.req.json());

// Store the new profile in the profiles collection
await profiles.set(id, profile);
try {
var profile = Profile.fromJson(ctx.req.json());
// Store the new profile in the profiles collection
await profiles.set(id, profile.toJson());

// Send a success response.
ctx.resp.body = "Profile $id created.";
// Send a success response.
ctx.resp.body = "Profile $id created.";
} on Exception catch (e) {
ctx.resp.status = 400;
ctx.resp.body = "An error occurred: $e";
}

return ctx;
});
Expand All @@ -62,7 +68,7 @@ void main() {
try {
// Retrieve and return the profile data
final profile = await profiles.get(id);
ctx.resp.json(profile.toJson());
ctx.resp.json(profile);
} on Exception catch (e) {
print(e);
ctx.resp.status = 404;
Expand Down Expand Up @@ -123,6 +129,4 @@ void main() {

return ctx;
});

Nitric.run();
}
1 change: 0 additions & 1 deletion lib/resource.dart

This file was deleted.

1 change: 1 addition & 0 deletions lib/resources.dart
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export 'src/resources/resources.dart';
export 'src/context/common.dart';
2 changes: 2 additions & 0 deletions lib/src/api/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export 'bucket.dart';
export 'keyvalue.dart';
export 'secret.dart';
export 'topic.dart';
export 'proto.dart';
export 'queue.dart';
Loading

0 comments on commit bf93fd0

Please sign in to comment.