#✅ - Gen 2: How to use function as field resolver in

1 messages · Page 1 of 1 (latest)

wet shell
#

Please how can I make a lambda resolver to a field in a model

basically converting this v1 code to use the v2 method
role: String @function(name: "lambda-${env}")

swift spruce
somber escarpBOT
#

✅ - Gen 2: How to use function as field resolver in

#

Answer selected!
@wet shell we can import the Func in the `resource.ts ` and define the function. The information is documented here. https://docs.amplify.aws/gen2/build-a-backend/data/custom-business-logic/#step-2---configure-custom-business-logic-handler-code do note that this is currently in active development
Kudos to @swift spruce!
#1186297606842876015 message

wet shell
#

Hey @swift spruce I actually looked at this earlier but I'm not quite clear how to add the functino to a particular field in a model, for more context, I want to add a lambda resolver to the subject field for example

Teacher: a .model({ subject: a.string().required(), institution: a.belongsTo('Institution'), })

wet shell
#

also the Func does not exist in @aws-amply/backend. posted and issue about this initially

swift spruce
# wet shell also the `Func` does not exist in `@aws-amply/backend`. posted and issue about ...

hey @wet shell , with the recent update for function in API resource.ts it appears the construct has changed from Func to defineFunction. The documentation update is currently on the way for this.
for first part i was able to create the following to call the function on a query but verifying a couple of things to ensure if the
is the same as https://docs.amplify.aws/javascript/build-a-backend/graphqlapi/custom-business-logic/#lambda-function-resolver

const schema = a.schema({
  Todo: a
    .model({
      content: a.customType({
        content: a.string(),
      }),
    })
    .authorization([a.allow.owner(), a.allow.public()]),

  echo: a
    .query()
    .arguments({
      content: a.string(),
    })
    .returns(a.ref("Todo"))
    .authorization([a.allow.public()])
    .function("test"),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: "apiKey",
    // API Key is used for a.allow.public() rules
    apiKeyAuthorizationMode: {
      expiresInDays: 30,
    },
  },
  functions: {
    test: defineFunction({
      entry: "./echo.ts",
      name: "test",
    }),
  },
});
wet shell
#

Alright. thank you @swift spruce , for now I have created a custom resolver with cdk was able to get it working. would love to be able to easily add the .function to the column just like you have on the query

swift spruce
#

hey reached out to the team and confirmed adding a function on field level is currently not yet supported and is being tracked internally.

wet shell
#

Alright, thank you @swift spruce

wet shell
#

@swift spruce if you don't mind me asking. is there a time this is expected to be released. does the amplify team have release dates for some of the things coming soon. even if their temporary

cos I added a custom resolver with cdk but it doesn't work out for my use case, the field is resolved after amplify pipeline resolvers have run but I need the field to be resolved before the amplify auth stage since It's being used to authorize dynamic roles

nova epoch
#

@wet shell We can't speak to solid timelines, but please continue to try and let us know the gaps you see, if it breaks, etc, your feedback helps a lot!

wet shell
#

Alright, thank you @nova epoch

bitter mesa
#

A field level resolver would be something I'd be interested in see as well. @nova epoch Is this still something that's not being tracked?

lime nest
#

Hey @wet shell did you have a code example of how you added the field resolver with CDK?

lime nest
#

Trying to see if there is a pattern people can provide which enables field level resolvers to be used until amplify team add this as a feature?

lament hornet
#

ok i have an absolutely terrible hack to get this to work...

I've used this SO question to guide my design of friendship tracking: https://dba.stackexchange.com/a/219566

tldr; use a separate table to act like an access log to track the state changes.

as such, a friendship should have it's latest status on it when it's resolved.

a.schema({
  FriendshipStatusType: a.enum(["PENDING", "ACCEPTED", "REJECTED", "BLOCKED"]),
  Friendship: a
    .model({
      requestingUserId: a
        .id()
        .required()
        .authorization((allow) => [allow.authenticated().to(["read"])]),
      requestedUserId: a
        .id()
        .required()
        .authorization((allow) => [allow.authenticated().to(["read"])]),

      requestingUser: a.belongsTo("User", "requestingUserId"),
      requestedUser: a.belongsTo("User", "requestedUserId"),
      statuses: a.hasMany("FriendshipStatus", [
        "requestingUserId",
        "requestedUserId",
      ]),
      status: a.ref("FriendshipStatusType").required(),
    }),
  FriendshipStatus: a
    .model({
      requestingUserId: a.id().required(),
      requestedUserId: a.id().required(),
      state: a.ref("FriendshipStatusType").required(),
      specifierId: a.id(),

      createdAt: a.datetime().required(),

      friendship: a.belongsTo("Friendship", [
        "requestingUserId",
        "requestedUserId",
      ]),
    })
})

I added the status field to Friendship as a ref.

Then, in my backend.ts, I've done some hacking...

/**
 * Extend the GraphQL Schema to add a status field to a friendship
 */
const _ = new CfnResolver(
  Stack.of(dataResources.graphqlApi),
  "Friendship.status",
  {
    apiId: dataResources.graphqlApi.apiId,
    dataSourceName: "FriendshipStatusTable",
    typeName: "Friendship",
    fieldName: "status",
    kind: "UNIT",
    runtime: {
      name: "APPSYNC_JS",
      runtimeVersion: "1.0.0",
    },
    code: fs
      .readFileSync(
        "./amplify/data/schema/dynamo/resolvers/friendship/status/index.js"
      )
      .toString(),
  }
);
#

I'm currently still trying to get this all to deploy successfully, but it is seemingly working... Most of my issues are because I've swapped between the L1/L2 constructs. Cleaning up my sandbox and redeploying now.