ãªã¢ã«ã¿ã€ã æ©èœã¯ããŠãŒã¶ãŒãããã«æŽæ°ããããåæ¹åã®äœéšãæ±ããçŸä»£ã®ã¢ããªã±ãŒã·ã§ã³ã«ãããŠäžå¯æ¬ ãšãªã£ãŠããŸãããã£ããã¢ããªãã©ã€ãããã·ã¥ããŒããã²ãŒã ã®ãªãŒããŒããŒããIoT ã·ã¹ãã ãªã©ãæ§ç¯ããå Žåã AWS AppSync Events 㯠WebSocket API ãéããŠãããã®ãªã¢ã«ã¿ã€ã æ©èœãå®çŸããã¹ã±ãŒãªã³ã°ãæ¥ç¶ç®¡çãæ°ã«ãããããšãªããã¹ã±ãŒã©ãã«ã§é«æ§èœãªãªã¢ã«ã¿ã€ã ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããããã«ããŠããŸãã AWS Lambda çšã® Powertools ã¯ãç£èŠããããåŠçã AWS Systems Manager Parameter Store çµ±åãåªçæ§ããã£ãŒãã£ãŒãã©ã°ã Amazon CloudWatch ã¡ããªã¯ã¹ãæ§é åãã°ãªã©ãå«ãéçºè
åãããŒã«ãããã§ããPowertools for AWS ã¯ãPythonãTypeScriptã.NET ã§æäŸãããæ°ãã AppSyncEventsResolver ãéããŠãAppSync Events ããµããŒãããããã«ãªããŸããããã®æ°æ©èœã«ãããããžãã¹ããžãã¯ã«éäžã§ããããã«èšèšãããæ©èœã匷åãããéçºäœéšãåäžããŸãã AppSyncEventsResolver ã¯ãã€ãã³ãã®åŠçã®ããã®ã·ã³ãã«ã§äžè²«ããã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããã€ãã³ãã®ãã£ã«ã¿ãªã³ã°ã倿ãã«ãŒãã£ã³ã°ãªã©ã®äžè¬çãªãã¿ãŒã³ã«å¯Ÿããçµã¿èŸŒã¿ãµããŒããæäŸãããŸãã ãã®èšäºã§ã¯ã TypeScript ã®äŸãèŠãŸããã Powertools for AWS (Python) ãš Powertools for AWS (.NET) ã䜿ãã°ãPython ãš .NET 颿°ã§ãåãæ©èœãå©çšã§ããŸãã å³ 1 â AWS AppSyncãLambdaãããã³ Powertools ã䜿çšãããªã¢ã«ã¿ã€ã ã€ãã³ããã³ããªã³ã°ã¢ãŒããã¯ãã£ãŒ æ¬ããã°ã§ã¯ã以äžã®ç¹ãåŠã³ãŸãã AppSyncEventsResolver ã䜿çšããŠã€ãã³ããã³ãã©ãèšå®ãã æé©ãªããã©ãŒãã³ã¹ã®ããã«ãããŸããŸãªã€ãã³ãåŠçãã¿ãŒã³ãå®è£
ãã ãã¿ãŒã³ããŒã¹ã®ã«ãŒãã£ã³ã°ã䜿çšããŠãã€ãã³ããã³ãã©ãæŽçãã äžè¬çãªäœ¿çšãã¿ãŒã³ã«å¯ŸããŠãçµã¿èŸŒã¿æ©èœã掻çšãã å§ãæ¹ AppSyncEventsResolver ã¯ã AWS Lambda 颿°å
ã§ã® AppSync Events ãåŠçããç°¡åã§å®£èšçãªæ¹æ³ã§ãããã®ã€ãã³ããªãŸã«ããŒã«ãã£ãŠã PUBLISH ã€ãã³ããš SUBSCRIBE ã€ãã³ãããªãã¹ã³ã§ããŸãã PUBLISH ã€ãã³ãã¯ãã¯ã©ã€ã¢ã³ãããã£ãã«ã«ã¡ãã»ãŒãžãéä¿¡ãããšãã«çºçããŸããäžæ¹ã SUBSCRIBE ã€ãã³ãã¯ãã¯ã©ã€ã¢ã³ãããã£ãã«ããµãã¹ã¯ãªãã·ã§ã³ããããšãããšãã«çºçããŸããç°ãªãåå空éããã£ãã«ã®ãã³ãã©ãç»é²ããããšã§ãã€ãã³ãé§ååã®éä¿¡ã管çã§ããŸãã æ¬¡ã«ãäœæ¥ãéå§ããŠããŸããŸãªéçºäœéšãåäžãããããã®äž»èŠæ©èœã«ã€ããŠèŠãŠãããŸãããã AppSyncEventsResolver ãèšå®ããåºæ¬çãªäŸã¯æ¬¡ã®ãšããã§ãã import { AppSyncEventsResolver, UnauthorizedException, } from '@aws-lambda-powertools/event-handler/appsync-events'; // Types for our message handling type ChatMessage = { userId: string ; content: string ; } // Simple authorization check const isAuthorized = (path: string, userId ?: string): boolean => { // check against your authorization system if (path.startsWith('/chat/private') && ! userId) { return false ; } return true ; }; // Message processing logic const processMessage = async (payload: ChatMessage) => { // - Validate message content // - Store in database // - Enrich with additional data return { ...payload, timestamp: new Date().toISOString() }; }; const app = new AppSyncEventsResolver(); // Handle publish events for a specific channel app.onPublish('/chat/general', async (payload: ChatMessage) => { // Process and return the message return processMessage(payload); }); // Handle subscription events for all channels app.onSubscribe('/*', async (info) => { const { channel: { path }, request, } = info ; // Perform access control checks if (! isAuthorized(path, userId)) { throw new UnauthorizedException(`not allowed to subscribe to ${ path } `); } return true ; }); export const handler = async (event, context) => app.resolve(event, context); AppSyncEventsResolver ã¯ã©ã¹ã¯ãåä¿¡ããã€ãã³ãããŒã¿ãè§£æããã€ãã³ãã®çš®é¡ã«å¿ããŠé©åãªãã³ãã©ã¡ãœãããåŒã³åºããŸããããã§äœãèµ·ãã£ãŠããã®ãã解説ããŸãããã ãã¿ãŒã³ããŒã¹ã®ã«ãŒãã£ã³ã° AppSyncEventsResolver ã¯ããã£ãã«ãã¹ã«åºã¥ããŠã€ãã³ããã³ãã©ãæŽçã§ããçŽæçãªãã¿ãŒã³ããŒã¹ã®ã«ãŒãã£ã³ã°ã·ã¹ãã ã䜿çšããŠããŸãã以äžã®ããšãå¯èœã§ãïŒ ç¹å®ã®ãã£ãã«ãåŠçããïŒ/chat/generalïŒ åå空éã«ã¯ã€ã«ãã«ãŒãã䜿çšããïŒ/chat/*ïŒ ã°ããŒãã«ãªãã£ãããªãŒã«ãã³ãã©ãäœæããïŒ/*ïŒ import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; const app = new AppSyncEventsResolver(); // Specific channel handler app.onPublish('/notifications/alerts', async (payload) => { // your logic here }); // Handle all channels in the notifications namespace app.onPublish('/notifications/*', async (payload) => { // your logic here }); // Global catch-all for unhandled channels app.onPublish('/*', async (payload) => { // your logic here }); export const handler = async (event, context) => app.resolve(event, context); æãäžè¬çãªãã£ãããªãŒã«ãã³ãã©ã¯ /* ã§ãããã¯ã©ã®åå空éããã£ãã«ã«ããããããŸããäžæ¹ã /default/* ã¯ã default åå空éã®ãããããã£ãã«ã«ãããããŸããè€æ°ã®ãã³ãã©ãåãã€ãã³ãã«ãããããå Žåã¯ãã©ã€ãã©ãªã¯æãå
·äœçãªãã³ãã©ãåŒã³åºããããäžè¬çãªãã³ãã©ã¯ç¡èŠãããŸããããšãã°ã /default/channel1 ã«å¯ŸããŠãã³ãã©ãç»é²ãããŠãããããã« /default/* ã«ããã³ãã©ãç»é²ãããŠããå ŽåãPowertools 㯠/default/channel1 ã«ãããããã€ãã³ãã§ã¯æåã®ãã³ãã©ãåŒã³åºãã2 çªç®ã®ãã³ãã©ã¯ç¡èŠãããŸãããã®ã¢ãããŒãã«ãããã€ãã³ããã©ã®ããã«åŠçãããããå¶åŸ¡ããäžèŠãªåŠçãåé¿ã§ããŸããããã©ã«ãã§ã¯ãPowertools ã¯ã©ã®ãã³ãã©ãšãåèŽããªãã€ãã³ãã«ã€ããŠã¯ããã®ãŸãŸã€ãã³ããè¿ããèŠåããã°ã«èšé²ããŸããã€ãŸãããããã£ãã€ãã³ãã¯å€æŽãããã«ãã®ãŸãŸæž¡ãããŸãããã®ã¢ãããŒãã¯ãç¹å®ã®ã€ãã³ãã«å¯ŸããŠã¯ã«ã¹ã¿ã ããžãã¯ãé©çšãã€ã€ãä»ã®ã€ãã³ãã¯ããã©ã«ãã®æåã§åŠçã§ãããããåŸã
ã«ã©ã€ãã©ãªãé©çšããŠããã®ã«åœ¹ç«ã¡ãŸãã Subscription ãã³ããªã³ã° Powertools ã¯ãµãã¹ã¯ãªãã·ã§ã³ã€ãã³ããåŠçããç°¡åãªæ¹æ³ãæäŸããŸããåä¿¡ããã€ãã³ããèªåçã«è§£æããã€ãã³ãã¿ã€ãã«åºã¥ããŠé©åãªãã³ãã©ãåŒã³åºããŸããããã©ã«ãã§ã¯ãLambda ãã³ãã©ããšã©ãŒãã¹ããŒãããèŠæ±ãæç€ºçã«æåŠããªãéããAppSync ã¯ãµãã¹ã¯ãªãã·ã§ã³ãèš±å¯ããŸãããµãã¹ã¯ãªãã·ã§ã³ãæåŠããããšãAppSync ã¯ã¯ã©ã€ã¢ã³ãã« 4xx ã¬ã¹ãã³ã¹ãè¿ãããµãã¹ã¯ãªãã·ã§ã³ã確ç«ãããã®ãé²ããŸãã import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; import type { Context } from 'aws-lambda'; const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'chat', singleMetric: true, }); const app = new AppSyncEventsResolver(); app.onSubscribe('/default/foo', (event) => { metrics.addDimension('channel', event.info.channel.path); metrics.addMetric('connections', MetricUnit.Count, 1); }); export const handler = async (event: unknown, context: Context) => app.resolve(event, context); ãµãã¹ã¯ãªãã·ã§ã³ã€ãã³ããå°çãããšããã®ã©ã€ãã©ãªã¯ã€ãã³ããªããžã§ã¯ãã第 1 åŒæ°ãšããŠãã³ãã©ãåŒã³åºããŸããã¢ã¯ã»ã¹å¶åŸ¡ãã§ãã¯ã®å®è¡ãªã©ããµãã¹ã¯ãªãã·ã§ã³ã€ãã³ãã«åºã¥ããŠå¿
èŠãªåŠçãè¡ããŸãã app.onSubscribe('/private/*', async (info) => { const userGroups = info.identity?.groups && Array.isArray(info.identity?.groups) ?info.identity ?.groups : [] ; const channelGroup = 'premium-users'; if (!userGroups.includes(channelGroup)) { throw new UnauthorizedException( `Subscription requires ${ channelGroup } group membership` ); } }) ãµãã¹ã¯ãªãã·ã§ã³ã€ãã³ãã¯åããããã³ã°ã«ãŒã«ã«åŸããã€ãã³ããšã³ã³ããã¹ããžã®å®å
šãªã¢ã¯ã»ã¹ãæäŸããŸããã¯ã€ã«ãã«ãŒã * æåã䜿çšããŠä»»æã®åå空éããã£ã³ãã«ã«å¯Ÿãããã£ãããªãŒã«ãã³ãã©ãç»é²ã§ãããã³ãã©å
ã§ã€ãã³ããšã³ã³ããã¹ããªããžã§ã¯ãã«å®å
šã«ã¢ã¯ã»ã¹ããããšãã§ããŸãã ã€ãã³ããšã³ã³ããã¹ãã®å®å
šãªã¢ã¯ã»ã¹ ãªãŸã«ããŒãã€ãã³ããã³ããªã³ã°ãç°¡çŽ åããŸãããå¿
èŠã«å¿ããŠã€ãã³ããšã³ã³ããã¹ããªããžã§ã¯ãã«å®å
šã«ã¢ã¯ã»ã¹ã§ããŸããããã¯ããªã¯ãšã¹ãããããŒã Lambda ã³ã³ããã¹ãã®æ®ãå®è¡æéãªã©ãã«ã¹ã¿ã ããžãã¯ãå®è£
ããããã«è¿œå æ
å ±ãå¿
èŠãªå Žåã«åœ¹ç«ã¡ãŸãã ãªãŸã«ããŒã¯ãå
šãŠã®ã€ãã³ããšã³ã³ããã¹ãã第 2 åŒæ°ãšç¬¬ 3 åŒæ°ãšããŠåãã³ãã©ã«æž¡ããŸããããã«ãããæ¢åã®ã³ãŒãã倿Žããããšãªããé¢é£ããå
šãŠã®æ
å ±ã«ã¢ã¯ã»ã¹ã§ããŸãã import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; import { Logger } from '@aws-lambda-powertools/logger'; const logger = new Logger({ logLeveL: 'INFO', serviceName: 'serverlessAirline' }); const app = new AppSyncEventsResolver({ logger }); app.onPublish('/orders/process', async (payload, event, context) => { // Access request headers const { headers } = event.request ; // Access Lambda context const { getRemainingTimeInMillis } = context ; logger.info('Processing event details', { headers, remainingTime: getRemainingTimeInMillis() }); return payload ; }); export const handler = async (event, context) => app.resolve(event, context); ãšã©ãŒãã³ããªã³ã° AppSyncEventsResolver ã«ã¯ãLambda 颿°ã®é害ãé²ããªããããšã©ãŒãé©åã« AppSync ã«éç¥ãããããçµã¿èŸŒã¿ã®ãšã©ãŒåŠçæ©èœããããŸããAppSync ã¯ãããã®ãšã©ãŒãã¯ã©ã€ã¢ã³ãã«äŒæãããŸãããã³ãã©ã§ãšã©ãŒãçºçããå ŽåããªãŸã«ã 㯠Lambda ã®åŒã³åºãå
šäœã倱æãããã®ã§ã¯ãªãããã®ãšã©ãŒãã€ãã³ãããšã®ã¬ã¹ãã³ã¹ãã€ããŒãã«å«ããŸãã ãã®ã¢ãããŒãã«ãããLambda 颿°ã¯å®è¡ãç¶ç¶ããªãããAppSync ã«é©åã«ãã©ãŒãããããããšã©ãŒã¡ãã»ãŒãžãæäŸããŸããè€æ°ã®ã€ãã³ããåŠçããå Žåã1ã€ã®ã€ãã³ãã倱æããŠããä»ã®ã€ãã³ãã¯æ£åžžã«åŠçãç¶ããŸããããã¯ãããã€ãã³ãã®ãšã©ãŒãä»ã®ã€ãã³ãã®åŠçã«åœ±é¿ãäžããªãããã«ããã䞊ååŠçã·ããªãªã§ç¹ã«åœ¹ç«ã¡ãŸãã import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; const app = new AppSyncEventsResolver(); app.onPublish('/messages', async (payload) => { // If message contains "error", throw an exception if (payload.message === "error") { throw new Error("Invalid message"); } return payload ; }); export const handler = async (event, context) => app.resolve(event, context); // When processing this event: // { // "id": "123", // "payload": { // "message": "error" // } // } // The resolver will return: // { // "id": "123", // "error": "Error - Invalid message" // } é«åºŠãªãã¿ãŒã³ãšãã¹ããã©ã¯ãã£ã¹ AppSyncEventsResolver ã«ã¯ãå
ç¢ã§ã¡ã³ããã³ã¹æ§ã®é«ããªã¢ã«ã¿ã€ã ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã®ã«åœ¹ç«ã€ãé«åºŠãªæ©èœã远å ãããŠããŸãããããã®æ©èœãšãã®å¹æçãªå©ç𿹿³ãèŠãŠãããŸãããã ãããªãã·ã¥åŠçã«ã€ã㊠ããã©ã«ãã§ã¯ãã¡ãã»ãŒãžããšã«ã«ãŒããã³ãã©ã 1 ååŒã³åºããŸããPowertools ãã¡ãã»ãŒãžã®å埩åŠçãã€ãã³ãã¬ã¹ãã³ã¹åœ¢åŒã®å€æãè¡ããããããžãã¹ããžãã¯ã«éäžããå®åã³ãŒããæžãå¿
èŠããããŸãããããšã¯ãã€ããŒããšããŠäœ¿ãããå€ãè¿ããããã®ã¡ãã»ãŒãžã§ãšã©ãŒãã¹ããŒããã ãã§ããã©ã€ãã©ãªããã€ããŒããæ£ããã€ãã³ã ID ãšé¢é£ä»ããŸãã import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; type SensorReading = { deviceId: string ; temperature: number ; humidity: number ; timestamp: string ; } const app = new AppSyncEventsResolver(); const metrics = new Metrics({ namespace: 'SensorReadings' }); app.onPublish('/sensors/readings', async (payload: SensorReading) => { // Process each sensor reading independently if (payload.temperature > 100) { metrics.addDimension('alertType', 'highTemperature'); metrics.addMetric('HighTemperature', MetricUnit.Count, 1); throw new Error('Temperature reading too high'); } // Enrich the payload with processing timestamp return { ...payload, processed: true, processedAt: new Date().toISOString() }; }); export const handler = async (event, context) => app.resolve(event, context); ãã®ãã¿ãŒã³ã¯ãåäžã®ã€ãã³ãã«å¯Ÿããããžãã¯ã®ã¿ãèšè¿°ããã°ãããããéçºãç°¡çŽ åããŸããPowertools ãæ®ããèªåçã«åŠçããŸãã éçŽåŠç éçŽã¢ãŒãã§ã¯ãã€ãã³ããåå¥ã«åŠçããã®ã§ã¯ãªããè€æ°ã®ã€ãã³ããåäžã®ããããšããŠåŠçããããšãã§ããŸããããã¯ãããŒã¿ããŒã¹ãžã®è€æ°ã®ã¯ãšãªã1åã®æäœã§éä¿¡ãããªã©ããªãœãŒã¹äœ¿çšãæé©åãããå ŽåããåŠçåã«è€æ°ã®ã€ãã³ãããŸãšããŠåæãããå Žåã«ç¹ã«åœ¹ç«ã¡ãŸããã©ã¡ãã®ã¢ãŒãã§ãã€ãã³ãåŠçãå®å
šã«å¶åŸ¡ã§ããŸãããéçŽã¢ãŒãã§ã¯äžåºŠã«ã€ãã³ãã®ãªã¹ãå
šäœã«ã¢ã¯ã»ã¹ã§ããŸãã ãããå®çŸããã«ã¯ã aggregate ãªãã·ã§ã³ã true ã«èšå®ããŸãããã®ã¢ãŒãã䜿çšãããšããªãŸã«ããŒã¯ã€ãã³ãã®ãªã¹ãå
šäœã1åã®åŒã³åºãã§ãã³ãã©ã«éä¿¡ããããããšããŠåŠçããããšãã§ããŸãã import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; const app = new AppSyncEventsResolver(); app.onPublish('/default/*', async (events) => { const results = [] ; for (const event of events) { try { results.push(await handleDefaultNamespaceCatchAll(event)); } catch (error) { results.push({ error: { errorType: 'Error', message: error.message, }, id: event.id, }); } } return results ; }, { aggregate: true, }); export const handler = async (event, context) => app.resolve(event, context); éçŽãªãã·ã§ã³ã¯ãããªãã·ã¥ã€ãã³ãã«ã®ã¿äœ¿çšå¯èœã§ããããã®ãªãã·ã§ã³ã䜿çšããå Žåã¯ãã€ãã³ãã®åŠçãšé©åãªã¬ã¹ãã³ã¹ã®è¿åŽã«è²¬ä»»ãæã€å¿
èŠãããããšã«æ³šæããŠãã ãããPowertools ã¯åŒãç¶ãã€ãã³ããæ£ãããã³ãã©ã«ã«ãŒãã£ã³ã°ããŸãããã€ãã³ãã®åŠçæ¹æ³ã¯å®å
šã«ããªãã®å¶åŸ¡äžã«ãããŸãã ã€ãã³ããã£ã«ã¿ãªã³ã° ã€ãã³ãããã£ã«ã¿ãªã³ã°ããã«ã¯ããã£ãã«ãã³ãã©ã§ãšã©ãŒãã¹ããŒããŸãããã³ãã©ãç¹å®ã®ã€ãã³ãã«å¯ŸããŠãšã©ãŒãã¹ããŒãããšãã©ã€ãã©ãªã¯ããããã£ããããåãã€ã³ããã¯ã¹ã®ã¬ã¹ãã³ã¹ãªã¹ãã«ãšã©ãŒãªããžã§ã¯ãã远å ããŸããããã¯ã察å¿ããã¡ãã»ãŒãžãç Žæ£ãã¹ãã§ããããšã瀺ããŸããããã«ãããã€ãã³ããéãã«ãã£ã«ã¿ãªã³ã°ãããããµãã¹ã¯ã©ã€ããŒã«æå³ã®ãããšã©ãŒãã£ãŒãããã¯ãæäŸããããéžæã§ããŸãã import { AppSyncEventsResolver } from '@aws-lambda-powertools/event-handler/appsync-events'; app.onPublish('/moderation/*', async (payload) => { // Filter out inappropriate content if (await containsInappropriateContent(payload)) { throw new CustomError('Content violates guidelines'); } // Process valid content return await processContent(payload); }); export const handler = async (event, context) => app.resolve(event, context); ãŸãšã Powertools for AWS ã® AppSyncEventsResolver ã¯ãã·ã³ãã«ã§äžè²«ããã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããããšã§ãAppSync Events ãåŠçããéçºäœéšãåäžãããŸããå®åã³ãŒããåæžããäžè¬çãªãã¿ãŒã³ã«å¯Ÿããçµã¿èŸŒã¿ãµããŒããæäŸããããšã§ãã€ã³ãã©ã³ãŒãã§ã¯ãªãããžãã¹ããžãã¯ã«éäžã§ããŸãã 詳现ã«ã€ããŠã¯ïŒ Powertools for AWS ã®ããã¥ã¡ã³ã ã§è©³çްæ
å ±ãæ¢çŽ¢ãã ãµãŒãã¹ã«ã€ããŠãã£ãšåŠã¶ããã« AppSync Event ã®ããã¥ã¡ã³ã ããã§ãã¯ãã è²¢ç®ãåé¡ãå ±åããããã«ç§ãã¡ã® GitHub ãªããžã㪠ã蚪åãã ãããã®æ°æ©èœã§äœãæ§ç¯ããã®ã楜ãã¿ã«ããŠããŸãããã£ãŒãããã¯ãå
±æããã¢ããªã±ãŒã·ã§ã³ã§ AppSyncEventsResolver ãã©ã®ããã«äœ¿çšããŠããããç¥ãããã ããïŒ æ¬ããã°ã¯ã Simplify AWS AppSync Events integration with Powertools for AWS Lambda ã ã翻蚳ãããã®ã§ãã 翻蚳è
ã«ã€ããŠ çš²ç° å€§éž AWS Japan ã§åãçãã¬ãè¶£å³ã®ãœãªã¥ãŒã·ã§ã³ã¢ãŒããã¯ãã奜ã㪠AWS ãµãŒãã¹ã¯ Amazon Location Service ãš AWS Amplify ã§ãæ¥æ¬ã®ã客æ§åãã« Amazon Location Service ã®è§£èª¬ããã° ãªã©ãå·çããŠããŸãã