运行时的 TypeScript捆绑和源映射 APPSYNC_JS - Amazon AppSync GraphQL
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

运行时的 TypeScript捆绑和源映射 APPSYNC_JS

TypeScript 通过提供类型安全和早期错误检测来增强 Amazon AppSync 开发。你可以在本地编写 TypeScript 代码,然后将其转换为, JavaScript 然后再将其与APPSYNC_JS运行时一起使用。该过程从为环境安装 TypeScript 和配置 tsconfig.json 开始。APPSYNC_JS然后,您可以使用 esbuild 等捆绑工具编译和捆绑代码。Amplify CLI 将从 GraphQL 架构生成类型,您可以在解析器代码中使用这些类型。

您可以在解析器和函数代码中使用自定义库和外部库,只要这些库符合 APPSYNC_JS 要求即可。捆绑工具将代码合并到单个文件中以供使用。 Amazon AppSync可以包含源映射,以帮助调试。

使用库并捆绑您的代码

在您的解析器和函数代码中,您可以使用自定义库和外部库,只要它们符合 APPSYNC_JS 要求即可。这样,就可以在应用程序中重复使用现有的代码。要使用由多个文件定义的库,必须使用捆绑工具(例如 esbuild)将代码合并到一个文件中,然后可以将其保存到 Amazon AppSync 解析器或函数中。

在捆绑代码时,请记住以下几点:

  • APPSYNC_JS仅支持 ECMAScript 模块 (ESM)。

  • @aws-appsync/* 模块集成到 APPSYNC_JS 中,不应将其与您的代码捆绑在一起。

  • APPSYNC_JS 运行时系统与 NodeJS 类似,即,不会在浏览器环境中运行代码。

  • 您可以包含可选的源映射。不过,不要包含源内容。

    要了解源映射的更多信息,请参阅使用源映射

例如,要捆绑位于 src/appsync/getPost.resolver.js 中的解析器代码,您可以使用以下 esbuild CLI 命令:

$ esbuild --bundle \ --sourcemap=inline \ --sources-content=false \ --target=esnext \ --platform=node \ --format=esm \ --external:@aws-appsync/utils \ --outdir=out/appsync \ src/appsync/getPost.resolver.js

构建您的代码并使用 TypeScript

TypeScript是一种由 Microsoft 开发 JavaScript的编程语言,它提供所有功能以及 TypeScript 打字系统。在将代码保存 TypeScript 到之前,您可以使用编写类型安全的代码并在构建时捕获错误和错误。 Amazon AppSync@aws-appsync/utils 包是完全类型化的。

APPSYNC_JS运行时不 TypeScript 直接支持。在将 TypeScript 代码保存到之前,必须先将 JavaScript 代码转换为APPSYNC_JS运行时支持的代码。 Amazon AppSync您可以使用 TypeScript 在本地集成开发环境 (IDE) 中编写代码,但请注意,您无法在 Amazon AppSync 控制台中创建 TypeScript 代码。

首先,请确保已在项目中TypeScript安装。然后,使用配置您的 TypeScript 转码设置以与APPSYNC_JS运行时配合使用TSConfig。以下是您可以使用的基本 tsconfig.json 文件示例:

// tsconfig.json { "compilerOptions": { "target": "esnext", "module": "esnext", "noEmit": true, "moduleResolution": "node", } }

然后,您可以使用 esbuild 等捆绑工具编译和捆绑代码。例如,给定一个项目,你的 Amazon AppSync 代码位于src/appsync,你可以使用以下命令来编译和捆绑你的代码:

$ esbuild --bundle \ --sourcemap=inline \ --sources-content=false \ --target=esnext \ --platform=node \ --format=esm \ --external:@aws-appsync/utils \ --outdir=out/appsync \ src/appsync/**/*.ts

使用 Amplify codegen

您可以使用 Amplify CLI 生成架构的类型。从 schema.graphql 文件所在的目录中,运行以下命令并查看提示以配置 codegen:

$ npx @aws-amplify/cli codegen add

要在某些情况下(例如,更新架构时)重新生成 codegen,请运行以下命令:

$ npx @aws-amplify/cli codegen

然后,您可以在解析器代码中使用生成的类型。例如,给定以下架构:

type Todo { id: ID! title: String! description: String } type Mutation { createTodo(title: String!, description: String): Todo } type Query { listTodos: Todo }

你可以在以下示例 Amazon AppSync 函数中使用生成的类型:

import { Context, util } from '@aws-appsync/utils' import * as ddb from '@aws-appsync/utils/dynamodb' import { CreateTodoMutationVariables, Todo } from './API' // codegen export function request(ctx: Context<CreateTodoMutationVariables>) { ctx.args.description = ctx.args.description ?? 'created on ' + util.time.nowISO8601() return ddb.put<Todo>({ key: { id: util.autoId() }, item: ctx.args }) } export function response(ctx) { return ctx.result as Todo }

在中使用泛型 TypeScript

您可以将泛型与提供的多种类型一起使用。例如,下面的代码片段是 Todo 类型:

export type Todo = { __typename: "Todo", id: string, title: string, description?: string | null, };

您可以为使用 Todo 的订阅编写解析器。在您的 IDE 中,类型定义和自动完成提示将指导您正确使用 toSubscriptionFilter 转换实用程序:

import { util, Context, extensions } from '@aws-appsync/utils' import { Todo } from './API' export function request(ctx: Context) { return {} } export function response(ctx: Context) { const filter = util.transform.toSubscriptionFilter<Todo>({ title: { beginsWith: 'hello' }, description: { contains: 'created' }, }) extensions.setSubscriptionFilter(filter) return null }

检查您的包

您可以导入 esbuild-plugin-eslint 插件以自动检查您的包。然后,您可以提供启用 ESLint 功能的 plugins 值以启用该插件。以下是在名为的文件中使用 esbuild JavaScript API 的片段:build.mjs

/* eslint-disable */ import { build } from 'esbuild' import eslint from 'esbuild-plugin-eslint' import glob from 'glob' const files = await glob('src/**/*.ts') await build({ format: 'esm', target: 'esnext', platform: 'node', external: ['@aws-appsync/utils'], outdir: 'dist/', entryPoints: files, bundle: true, plugins: [eslint({ useEslintrc: true })], })

使用源映射

您可以在 JavaScript 代码中提供内联源映射 (sourcemap)。当您打包 JavaScript 或 TypeScript 编写代码并希望在日志和运行时 JavaScript 错误消息中查看对输入源文件的引用时,源映射非常有用。

您的 sourcemap 必须出现在代码末尾。它是由采用以下格式的单个注释行定义的:

//# sourceMappingURL=data:application/json;base64,<base64 encoded string>

示例如下:

//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibGliLmpzIiwgImNvZGUuanMiXSwKICAibWFwcGluZ3MiOiAiO0FBQU8sU0FBUyxRQUFRO0FBQ3RCLFNBQU87QUFDVDs7O0FDRE8sU0FBUyxRQUFRLEtBQUs7QUFDM0IsU0FBTyxNQUFNO0FBQ2Y7IiwKICAibmFtZXMiOiBbXQp9Cg==

可以使用 esbuild 创建源映射。以下示例向您展示了在构建和捆绑代码时如何使用 esbuild JavaScript API 来包含内联源映射:

/* eslint-disable */ import { build } from 'esbuild' import eslint from 'esbuild-plugin-eslint' import glob from 'glob' const files = await glob('src/**/*.ts') await build({ sourcemap: 'inline', sourcesContent: false, format: 'esm', target: 'esnext', platform: 'node', external: ['@aws-appsync/utils'], outdir: 'dist/', entryPoints: files, bundle: true, plugins: [eslint({ useEslintrc: true })], })

特别是,sourcemapsourcesContent 选项指定应在每个构建末尾的行中添加源映射,但源映射不应包含源内容。作为惯例,我们建议不要在您的 sourcemap 中包含源内容。您可以将 sources-content 设置为 false 以在 esbuild 中禁用该功能。

要说明源映射的工作方式,请查看以下示例,其中解析器代码引用帮助程序库中的帮助程序函数。该代码在解析器代码和帮助程序库中包含日志语句:

./src/default.resolver.ts(您的解析器)

import { Context } from '@aws-appsync/utils' import { hello, logit } from './helper' export function request(ctx: Context) { console.log('start >') logit('hello world', 42, true) console.log('< end') return 'test' } export function response(ctx: Context): boolean { hello() return ctx.prev.result }

.src/helper.ts(帮助程序文件)

export const logit = (...rest: any[]) => { // a special logger console.log('[logger]', ...rest.map((r) => `<${r}>`)) } export const hello = () => { // This just returns a simple sentence, but it could do more. console.log('i just say hello..') }

在您构建并捆绑解析器文件时,您的解析器代码将包含内联源映射。当您的解析器运行时, CloudWatch 日志中会显示以下条目:

CloudWatch log entries showing resolver code execution with inline source map information.

查看 CloudWatch 日志中的条目,您会注意到这两个文件的功能已捆绑在一起并行运行。每个文件的原始文件名也清晰地反映在日志中。