diff --git a/src/pages/[platform]/build-a-backend/data/connect-to-existing-data-sources/connect-postgres-mysql-database/index.mdx b/src/pages/[platform]/build-a-backend/data/connect-to-existing-data-sources/connect-postgres-mysql-database/index.mdx index b919d0e4a35..1efa65df3f9 100644 --- a/src/pages/[platform]/build-a-backend/data/connect-to-existing-data-sources/connect-postgres-mysql-database/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/connect-to-existing-data-sources/connect-postgres-mysql-database/index.mdx @@ -208,7 +208,7 @@ When deploying your app to production, you need to [add the database connection ## Rename generated models and fields -To improve the ergonomics of your API, you might want to rename the generate fields or types to better accommodate your use case. Use the `renameModels()` and `renameModelFields()` modifiers to rename the auto-inferred data models and their fields. +To improve the ergonomics of your API, you might want to rename the generate fields or types to better accommodate your use case. Use the `renameModels()` modifier to rename the auto-inferred data models. ```ts // Rename models or fields to be more idiomatic for frontend code diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-polly/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-polly/index.mdx index ccd7697d650..03f73f3c676 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-polly/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-polly/index.mdx @@ -218,6 +218,7 @@ Amplify.configure(outputs); Example frontend code to create an audio buffer for playback using a text input. + ```ts title="App.tsx" import "./App.css"; import { generateClient } from "aws-amplify/api"; @@ -267,4 +268,53 @@ function App() { export default App; ``` + + +```ts title="app.component.ts" +import type { Schema } from '../../../amplify/data/resource'; +import { Component } from '@angular/core'; +import { generateClient } from 'aws-amplify/api'; +import { getUrl } from 'aws-amplify/storage'; + +const client = generateClient(); + +type PollyReturnType = Schema['convertTextToSpeech']['returnType']; + +@Component({ + selector: 'app-root', + template: ` +
+ + + Get audio file +
+ `, + styleUrls: ['./app.component.css'], +}) +export class App { + src: string = ''; + file: PollyReturnType = ''; + + async synthesize() { + const { data, errors } = await client.mutations.convertTextToSpeech({ + text: 'Hello World!', + }); + + if (!errors && data) { + this.file = data; + } else { + console.log(errors); + } + } + + async fetchAudio() { + const res = await getUrl({ + path: 'public/' + this.file, + }); + + this.src = res.url.toString(); + } +} +``` +
diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-rekognition/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-rekognition/index.mdx index 61378979b58..91e4d3db8a5 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-rekognition/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-amazon-rekognition/index.mdx @@ -219,6 +219,7 @@ Amplify.configure(outputs); This code sets up a React app to upload an image to an S3 bucket and then use Amazon Rekognition to recognize the text in the uploaded image. + ```ts title="App.tsx" import { type ChangeEvent, useState } from "react"; import { generateClient } from "aws-amplify/api"; @@ -282,3 +283,71 @@ function App() { export default App; ``` + + +```ts title="app.component.ts" +import type { Schema } from '../../../amplify/data/resource'; +import { Component } from '@angular/core'; +import { generateClient } from 'aws-amplify/api'; +import { uploadData } from 'aws-amplify/storage'; +import { CommonModule } from '@angular/common'; + +// Generating the client +const client = generateClient(); + +type IdentifyTextReturnType = Schema['identifyText']['returnType']; + +@Component({ + selector: 'app-text-recognition', + standalone: true, + imports: [CommonModule], + template: ` +
+

Amazon Rekognition Text Recognition

+
+ + +
+

Recognized Text:

+ {{ textData }} +
+
+
+ `, +}) +export class TodosComponent { + // Component properties instead of React state + path: string = ''; + textData?: IdentifyTextReturnType; + + // Function to handle file upload to S3 bucket + async handleTranslate(event: Event) { + const target = event.target as HTMLInputElement; + if (target.files && target.files.length > 0) { + const file = target.files[0]; + const s3Path = 'public/' + file.name; + + try { + await uploadData({ + path: s3Path, + data: file, + }); + + this.path = s3Path; + } catch (error) { + console.error(error); + } + } + } + + // Function to recognize text from the uploaded image + async recognizeText() { + // Identifying text in the uploaded image + const { data } = await client.queries.identifyText({ + path: this.path, // File name + }); + this.textData = data; + } +} +``` +
diff --git a/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-bedrock/index.mdx b/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-bedrock/index.mdx index b141491b60b..3c5727deb69 100644 --- a/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-bedrock/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/custom-business-logic/connect-bedrock/index.mdx @@ -350,6 +350,7 @@ const { data, errors } = await client.queries.generateHaiku({ Here's an example of a simple UI that prompts a generative AI model to create a haiku based on user input: + ```tsx title="App.tsx" import type { Schema } from '@/amplify/data/resource'; import type { FormEvent } from 'react'; @@ -402,6 +403,65 @@ export default function App() { ); } ``` + + + +```ts title="app.component.ts" +import type { Schema } from '../../../amplify/data/resource'; +import { Component } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { Amplify } from 'aws-amplify'; +import { generateClient } from 'aws-amplify/api'; +import outputs from '../../../amplify_outputs.json'; + +Amplify.configure(outputs); + +const client = generateClient(); + +@Component({ + selector: 'app-haiku', + standalone: true, + imports: [FormsModule], + template: ` +
+
+

Haiku Generator

+
+ +
+
+
{{ answer }}
+
+
+
+ `, +}) +export class HaikuComponent { + prompt: string = ''; + answer: string | null = null; + + async sendPrompt() { + const { data, errors } = await client.queries.generateHaiku({ + prompt: this.prompt, + }); + + if (!errors) { + this.answer = data; + this.prompt = ''; + } else { + console.log(errors); + } + } +} +``` +
![A webpage titled "Haiku Generator" and input field. "Frank Herbert's Dune" is entered and submitted. Shortly after, a haiku is rendered to the page.](/images/haiku-generator.gif) diff --git a/src/pages/[platform]/build-a-backend/data/query-data/index.mdx b/src/pages/[platform]/build-a-backend/data/query-data/index.mdx index 0b1402143aa..19ccffbcfef 100644 --- a/src/pages/[platform]/build-a-backend/data/query-data/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/query-data/index.mdx @@ -147,6 +147,8 @@ const { }); ``` + + If you're building a React application, you can use the `usePagination` hook in Amplify UI to help with managing the pagination user experience. ```js @@ -187,6 +189,8 @@ export const PaginationHasMorePagesExample = () => { }; ``` + + **Limitations:** @@ -214,7 +218,11 @@ const { data: blogWithSubsetOfData, errors } = await client.models.Blog.get( ## TypeScript type helpers for Amplify Data -When using TypeScript, you frequently need to specify data model types for type generics. For instance, with React's `useState`, you provide a type in TypeScript to ensure type-safety in your component code using the state. Use the `Schema["MODEL_NAME"]["type"]` pattern to get TypeScript types for the shapes of data models returned from the backend API. This allows you to get consumable TypeScript types for the shapes of the data model return values coming from the backend API. +When using TypeScript, you frequently need to specify data model types for type generics. + + + +For instance, with React's `useState`, you provide a type in TypeScript to ensure type-safety in your component code using the state. Use the `Schema["MODEL_NAME"]["type"]` pattern to get TypeScript types for the shapes of data models returned from the backend API. ```ts import { type Schema } from '@/amplify/data/resource'; @@ -224,8 +232,21 @@ type Post = Schema['Post']['type']; const [posts, setPosts] = useState([]); ``` + + + + +```ts +import { type Schema } from '../../../amplify/data/resource'; + +type Post = Schema['Post']['type']; +``` + + + You can combine the `Schema["MODEL_NAME"]["type"]` type with the `SelectionSet` helper type to describe the return type of API requests using the `selectionSet` parameter: + ```ts import type { SelectionSet } from 'aws-amplify/data'; import type { Schema } from '../amplify/data/resource'; @@ -245,6 +266,86 @@ const fetchPosts = async () => { } ``` + + + +```ts + + + +``` + + + +```ts +import type { Schema } from '../../../amplify/data/resource'; +import { Component, OnInit } from '@angular/core'; +import { generateClient, type SelectionSet } from 'aws-amplify/data'; +import { CommonModule } from '@angular/common'; + +const client = generateClient(); + +const selectionSet = ['content', 'blog.author.*', 'comments.*'] as const; + +type PostWithComments = SelectionSet< + Schema['Post']['type'], + typeof selectionSet +>; + +@Component({ + selector: 'app-todos', + standalone: true, + imports: [CommonModule], + templateUrl: './todos.component.html', + styleUrls: ['./todos.component.css'], +}) +export class TodosComponent implements OnInit { + posts: PostWithComments[] = []; + + constructor() {} + + ngOnInit(): void { + this.fetchPosts(); + } + + async fetchPosts(): Promise { + const { data: postsWithComments } = await client.models.Post.list({ + selectionSet, + }); + this.posts = postsWithComments; + } +} +``` + + ## Cancel read requests You can cancel any query API request by calling `.cancel` on the query request promise that's returned by `.list(...)` or `.get(...)`. diff --git a/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx b/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx index 26542619284..01125c78b9e 100644 --- a/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx +++ b/src/pages/[platform]/build-a-backend/data/set-up-data/index.mdx @@ -383,8 +383,7 @@ Let's first add a button to create a new todo item. To make a "create Todo" API - - + ```tsx title="src/TodoList.tsx" import type { Schema } from '../amplify/data/resource' @@ -405,7 +404,6 @@ export default function TodoList() { } ``` - @@ -432,11 +430,41 @@ async function createTodo() { ``` - +Run the application in local development mode with `npm run dev` and check your network tab after creating a todo. You should see a successful request to a `/graphql` endpoint. + + + +Try playing around with the code completion of `.update(...)` and `.delete(...)` to get a sense of other mutation operations. + + + + + +```ts title="todo-list.component.ts" +import type { Schema } from '../amplify/data/resource'; +import { Component } from '@angular/core'; +import { generateClient } from 'aws-amplify/data'; +const client = generateClient(); + +@Component({ + selector: 'app-todo-list', + template: ` + + ` +}) +export class TodoListComponent { + async createTodo() { + await client.models.Todo.create({ + content: window.prompt("Todo content?"), + isDone: false + }); + } +} +``` Run the application in local development mode and check your network tab after creating a todo. You should see a successful request to a `/graphql` endpoint. @@ -445,8 +473,8 @@ Run the application in local development mode and check your network tab after c Try playing around with the code completion of `.update(...)` and `.delete(...)` to get a sense of other mutation operations. - + In your MainActivity, add a button to create a new todo. @@ -637,9 +665,7 @@ Creating Todo successful. Next, list all your todos and then refetch the todos after a todo has been added: - - - + ```tsx title="src/TodoList.tsx" import { useState, useEffect } from "react"; import type { Schema } from "../amplify/data/resource"; @@ -684,7 +710,6 @@ export default function TodoList() { - ```html title="src/TodoList.vue"