diff --git a/libs/wingsdk/src/cloud/api.ts b/libs/wingsdk/src/cloud/api.ts index ae6b2679950..a5c4969d321 100644 --- a/libs/wingsdk/src/cloud/api.ts +++ b/libs/wingsdk/src/cloud/api.ts @@ -629,6 +629,15 @@ export interface ApiConnectOptions {} */ export interface IApiClient {} +/** + * List of inflight operations available for `Api`. + * @internal + */ +export enum ApiInflightMethods { + /** When the API endpoint receives a request. */ + REQUEST = "request", +} + /** * Allowed HTTP methods for a endpoint. */ diff --git a/libs/wingsdk/src/cloud/bucket.ts b/libs/wingsdk/src/cloud/bucket.ts index e9fe998bbb2..2372be10269 100644 --- a/libs/wingsdk/src/cloud/bucket.ts +++ b/libs/wingsdk/src/cloud/bucket.ts @@ -1,7 +1,7 @@ import * as fs from "fs"; import { isAbsolute, resolve } from "path"; import { Construct } from "constructs"; -import { ITopicOnMessageHandler, Topic } from "./topic"; +import { ITopicOnMessageHandler, Topic, TopicInflightMethods } from "./topic"; import { fqnForType } from "../constants"; import { App } from "../core"; import { AbstractMemberError } from "../core/errors"; @@ -143,6 +143,7 @@ export class Bucket extends Resource { source: this, sourceOp: op, target: topic, + targetOp: TopicInflightMethods.PUBLISH, name: BucketEventType.CREATE, }); } @@ -159,6 +160,7 @@ export class Bucket extends Resource { source: this, sourceOp: op, target: topic, + targetOp: TopicInflightMethods.PUBLISH, name: BucketEventType.UPDATE, }); } @@ -175,6 +177,7 @@ export class Bucket extends Resource { source: this, sourceOp: op, target: topic, + targetOp: TopicInflightMethods.PUBLISH, name: BucketEventType.DELETE, }); } diff --git a/libs/wingsdk/src/cloud/schedule.ts b/libs/wingsdk/src/cloud/schedule.ts index bd9e12094e1..4d8543be0af 100644 --- a/libs/wingsdk/src/cloud/schedule.ts +++ b/libs/wingsdk/src/cloud/schedule.ts @@ -121,6 +121,15 @@ export interface IScheduleOnTickHandler extends IInflight { */ export interface IScheduleClient {} +/** + * List of inflight operations available for `Schedule`. + * @internal + */ +export enum ScheduleInflightMethods { + /** When the schedule runs its scheduled actions. */ + TICK = "tick", +} + /** * Inflight client for `IScheduleOnTickHandler`. */ diff --git a/libs/wingsdk/src/std/resource.ts b/libs/wingsdk/src/std/resource.ts index 4c9d8cb00bb..3494103f9f1 100644 --- a/libs/wingsdk/src/std/resource.ts +++ b/libs/wingsdk/src/std/resource.ts @@ -98,6 +98,10 @@ export interface IHostedLiftable extends ILiftable { onLift(host: IInflightHost, ops: string[]): void; } +function hasLiftMap(x: any): x is { _liftMap: LiftMap } { + return x != null && typeof x._liftMap === "object"; +} + /** * Abstract interface for `Resource`. * @skipDocs @@ -193,26 +197,33 @@ export abstract class Resource extends Construct implements IResource { * @internal */ public _preSynthesize(): void { - if ((this as IHostedLiftable)._liftMap === undefined) { - return; + if (hasLiftMap(this) && !(this instanceof AutoIdResource)) { + addConnectionsFromLiftMap(this, this._liftMap); } + } +} - const data = (this as IHostedLiftable)._liftMap!; - for (const [op, liftEntries] of Object.entries(data)) { - for (const [dep, depOps] of liftEntries) { - if (!Construct.isConstruct(dep)) { - continue; - } - +function addConnectionsFromLiftMap( + construct: IConstruct, + liftData: LiftMap, + baseOp?: string +) { + for (const [op, liftEntries] of Object.entries(liftData)) { + for (const [dep, depOps] of liftEntries) { + if (Construct.isConstruct(dep) && !(dep instanceof AutoIdResource)) { + // case 1: dep is an ordinary resource for (const depOp of depOps) { - Node.of(this).addConnection({ - source: this, - sourceOp: op, + Node.of(construct).addConnection({ + source: construct, + sourceOp: baseOp ?? op, target: dep, targetOp: depOp, name: depOp, }); } + } else if (hasLiftMap(dep)) { + // case 2: dep is an inflight + addConnectionsFromLiftMap(construct, dep._liftMap, baseOp ?? op); } } } diff --git a/libs/wingsdk/src/target-sim/api.ts b/libs/wingsdk/src/target-sim/api.ts index 4326ea8f14c..593d4237549 100644 --- a/libs/wingsdk/src/target-sim/api.ts +++ b/libs/wingsdk/src/target-sim/api.ts @@ -126,8 +126,10 @@ export class Api extends cloud.Api implements ISimulatorResource { const fn = this.createOrGetFunction(inflight, props, path, method); Node.of(this).addConnection({ source: this, + sourceOp: cloud.ApiInflightMethods.REQUEST, target: fn, - name: `${method.toLowerCase()}()`, + targetOp: cloud.FunctionInflightMethods.INVOKE, + name: `${method.toLowerCase()} ${path}`, }); this.policy.addStatement(fn, cloud.FunctionInflightMethods.INVOKE); } diff --git a/libs/wingsdk/src/target-sim/queue.ts b/libs/wingsdk/src/target-sim/queue.ts index cfe9fb382b8..ffd0542a59f 100644 --- a/libs/wingsdk/src/target-sim/queue.ts +++ b/libs/wingsdk/src/target-sim/queue.ts @@ -59,7 +59,9 @@ export class Queue extends cloud.Queue implements ISimulatorResource { Node.of(this).addConnection({ source: this, + sourceOp: cloud.QueueInflightMethods.POP, target: this.dlq.queue, + targetOp: cloud.QueueInflightMethods.PUSH, name: "dead-letter queue", }); } diff --git a/libs/wingsdk/src/target-sim/schedule.ts b/libs/wingsdk/src/target-sim/schedule.ts index a8dacb71a3a..4fc7ad8db39 100644 --- a/libs/wingsdk/src/target-sim/schedule.ts +++ b/libs/wingsdk/src/target-sim/schedule.ts @@ -54,7 +54,9 @@ export class Schedule extends cloud.Schedule implements ISimulatorResource { Node.of(this).addConnection({ source: this, + sourceOp: cloud.ScheduleInflightMethods.TICK, target: fn, + targetOp: cloud.FunctionInflightMethods.INVOKE, name: "onTick()", }); this.policy.addStatement(fn, cloud.FunctionInflightMethods.INVOKE); diff --git a/libs/wingsdk/src/target-sim/topic.ts b/libs/wingsdk/src/target-sim/topic.ts index c10485ecc53..a34b77889c8 100644 --- a/libs/wingsdk/src/target-sim/topic.ts +++ b/libs/wingsdk/src/target-sim/topic.ts @@ -79,7 +79,9 @@ export class Topic extends cloud.Topic implements ISimulatorResource { Node.of(this).addConnection({ source: this, + sourceOp: cloud.TopicInflightMethods.PUBLISH, target: fn, + targetOp: cloud.FunctionInflightMethods.INVOKE_ASYNC, name: "subscribeQueue()", }); diff --git a/libs/wingsdk/src/target-tf-aws/api.ts b/libs/wingsdk/src/target-tf-aws/api.ts index d230760bcce..0480b76916d 100644 --- a/libs/wingsdk/src/target-tf-aws/api.ts +++ b/libs/wingsdk/src/target-tf-aws/api.ts @@ -83,7 +83,9 @@ export class Api extends cloud.Api implements IAwsApi { Node.of(this).addConnection({ source: this, + sourceOp: cloud.ApiInflightMethods.REQUEST, target: fn, + targetOp: cloud.FunctionInflightMethods.INVOKE, name: `${lowerMethod}()`, }); } diff --git a/libs/wingsdk/src/target-tf-aws/queue.ts b/libs/wingsdk/src/target-tf-aws/queue.ts index 17a1b9c2325..39f1daa7fc1 100644 --- a/libs/wingsdk/src/target-tf-aws/queue.ts +++ b/libs/wingsdk/src/target-tf-aws/queue.ts @@ -115,7 +115,9 @@ export class Queue extends cloud.Queue implements IAwsQueue { Node.of(this).addConnection({ source: this, + sourceOp: cloud.QueueInflightMethods.PUSH, target: fn, + targetOp: cloud.FunctionInflightMethods.INVOKE, name: "setConsumer()", }); diff --git a/libs/wingsdk/src/target-tf-aws/schedule.ts b/libs/wingsdk/src/target-tf-aws/schedule.ts index 03a74749c64..f0a6bc1edaa 100644 --- a/libs/wingsdk/src/target-tf-aws/schedule.ts +++ b/libs/wingsdk/src/target-tf-aws/schedule.ts @@ -75,7 +75,9 @@ export class Schedule extends cloud.Schedule { Node.of(this).addConnection({ source: this, + sourceOp: cloud.ScheduleInflightMethods.TICK, target: fn, + targetOp: cloud.FunctionInflightMethods.INVOKE, name: "onTick()", }); diff --git a/libs/wingsdk/src/target-tf-aws/topic.ts b/libs/wingsdk/src/target-tf-aws/topic.ts index a7fc8e3936b..3c635f47a99 100644 --- a/libs/wingsdk/src/target-tf-aws/topic.ts +++ b/libs/wingsdk/src/target-tf-aws/topic.ts @@ -82,7 +82,9 @@ export class Topic extends cloud.Topic implements IAwsTopic { Node.of(this).addConnection({ source: this, + sourceOp: cloud.TopicInflightMethods.PUBLISH, target: fn, + targetOp: cloud.FunctionInflightMethods.INVOKE_ASYNC, name: "onMessage()", }); diff --git a/libs/wingsdk/src/target-tf-gcp/schedule.ts b/libs/wingsdk/src/target-tf-gcp/schedule.ts index 368d3491781..fe4494853f2 100644 --- a/libs/wingsdk/src/target-tf-gcp/schedule.ts +++ b/libs/wingsdk/src/target-tf-gcp/schedule.ts @@ -86,7 +86,9 @@ export class Schedule extends cloud.Schedule { Node.of(this).addConnection({ source: this, + sourceOp: cloud.ScheduleInflightMethods.TICK, target: cronFunction, + targetOp: cloud.FunctionInflightMethods.INVOKE, name: "onTick()", }); diff --git a/libs/wingsdk/test/target-sim/__snapshots__/api.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/api.test.ts.snap index 76f042a12db..3af2f6ed541 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/api.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/api.test.ts.snap @@ -48,14 +48,18 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "post()", + "name": "post /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -392,9 +396,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -716,9 +722,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -1041,9 +1049,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -1366,9 +1376,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -1691,9 +1703,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -2033,39 +2047,53 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "post()", + "name": "post /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "put()", + "name": "put /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "delete()", + "name": "delete /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "head()", + "name": "head /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "options()", + "name": "options /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "patch()", + "name": "patch /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -2471,9 +2499,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /:name/:age", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -2812,9 +2842,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /:name", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -3126,9 +3158,18 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello/foo", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", + }, + { + "name": "get /hello/bat", + "source": "root/my_api", + "sourceOp": "request", + "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -3515,14 +3556,18 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "post()", + "name": "post /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler1", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -3966,14 +4011,18 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello/world", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, { - "name": "get()", + "name": "get /hello/wingnuts", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler1", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -4370,9 +4419,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -4694,9 +4745,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "get()", + "name": "get /users/:name", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -5028,9 +5081,11 @@ exports.handler = async function(event) { "connections.json": { "connections": [ { - "name": "post()", + "name": "post /hello", "source": "root/my_api", + "sourceOp": "request", "target": "root/my_api/OnRequestHandler0", + "targetOp": "invoke", }, ], "version": "connections-0.1", diff --git a/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap index 4a07cce8f33..4e8fab3c30c 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/file-counter.test.ts.snap @@ -196,6 +196,34 @@ bucket: (function() { "target": "root/HelloWorld/Counter/Resource", "targetOp": "call", }, + { + "name": "inc", + "source": "root/HelloWorld/Queue/Consumer0", + "sourceOp": "invoke", + "target": "root/HelloWorld/Counter", + "targetOp": "inc", + }, + { + "name": "put", + "source": "root/HelloWorld/Queue/Consumer0", + "sourceOp": "invoke", + "target": "root/HelloWorld/Bucket", + "targetOp": "put", + }, + { + "name": "inc", + "source": "root/HelloWorld/Queue/Consumer0", + "sourceOp": "invokeAsync", + "target": "root/HelloWorld/Counter", + "targetOp": "inc", + }, + { + "name": "put", + "source": "root/HelloWorld/Queue/Consumer0", + "sourceOp": "invokeAsync", + "target": "root/HelloWorld/Bucket", + "targetOp": "put", + }, ], "version": "connections-0.1", }, diff --git a/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap index 718f24e615f..7dfd136f097 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/queue.test.ts.snap @@ -1035,6 +1035,20 @@ exports.handler = async function(event) { "target": "root/my_queue/Consumer0", "targetOp": "invoke", }, + { + "name": "push", + "source": "root/my_queue_messages/Function", + "sourceOp": "invoke", + "target": "root/my_queue", + "targetOp": "push", + }, + { + "name": "push", + "source": "root/my_queue_messages/Function", + "sourceOp": "invokeAsync", + "target": "root/my_queue", + "targetOp": "push", + }, ], "version": "connections-0.1", }, diff --git a/libs/wingsdk/test/target-sim/__snapshots__/schedule.test.ts.snap b/libs/wingsdk/test/target-sim/__snapshots__/schedule.test.ts.snap index bc6b85216ff..2a517de9603 100644 --- a/libs/wingsdk/test/target-sim/__snapshots__/schedule.test.ts.snap +++ b/libs/wingsdk/test/target-sim/__snapshots__/schedule.test.ts.snap @@ -193,7 +193,9 @@ exports.handler = async function(event) { { "name": "onTick()", "source": "root/my_schedule", + "sourceOp": "tick", "target": "root/my_schedule/OnTick0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -441,7 +443,9 @@ exports.handler = async function(event) { { "name": "onTick()", "source": "root/my_schedule", + "sourceOp": "tick", "target": "root/my_schedule/OnTick0", + "targetOp": "invoke", }, ], "version": "connections-0.1", @@ -689,7 +693,9 @@ exports.handler = async function(event) { { "name": "onTick()", "source": "root/my_schedule", + "sourceOp": "tick", "target": "root/my_schedule/OnTick0", + "targetOp": "invoke", }, ], "version": "connections-0.1",