aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
87 stars 75 forks source link

Failed to start API Mocking - Callback must be a function #1234

Open morepe opened 1 year ago

morepe commented 1 year ago

How did you install the Amplify CLI?

npm

If applicable, what version of Node.js are you using?

v16.17.1

Amplify CLI Version

10.7.1

What operating system are you using?

Ubuntu (running in WSL2 on Windows)

Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.

No

Describe the bug

I can not start the mocking after I added some models connected to each other. It fails with: "MockProcessFault: Failed to start API Mocking.. Reason: Callback must be a function. Received undefined"

The API itself works fine if I access it in Amplify

Schema that I used:

type Variations @model @auth(rules: [{allow: public}]) { id: ID! displayName: String productID: ID! @index(name: "byProduct") }

type Store @model @auth(rules: [{allow: public}]) { id: ID! key: String! displayName: String! Products: [Product] @hasMany(indexName: "byStore", fields: ["id"]) }

type Product @model @auth(rules: [{allow: public}]) { id: ID! key: String! displayName: String! minimalPrice: Float! storeID: ID! @index(name: "byStore") Variations: [Variations] @hasMany(indexName: "byProduct", fields: ["id"]) }

Expected behavior

Mocking should start

Reproduction steps

Project Identifier

fb64912b3b591b6c0a306f250c9e5824

Log output

``` # Put your logs below this line amplify mock ✅ GraphQL schema compiled successfully. Edit your schema at /home/pmoretti/projekte/techstack-serverless/infonova-ecommerce-layer/amplify/backend/api/infonovaEcommerce/schema.graphql or place .graphql files in a directory at /home/pmoretti/projekte/techstack-serverless/infonova-ecommerce-layer/amplify/backend/api/infonovaEcommerce/schema Failed to start API Mocking. Running cleanup tasks. MockProcessFault: Failed to start API Mocking.. Reason: Callback must be a function. Received undefined at APITest.start (/snapshot/repo/build/node_modules/amplify-util-mock/lib/api/api.js:151:13) at processTicksAndRejections (internal/process/task_queues.js:95:5) at async start (/snapshot/repo/build/node_modules/amplify-util-mock/lib/api/index.js:18:5) at async Promise.all (index 0) at async mockAllCategories (/snapshot/repo/build/node_modules/amplify-util-mock/lib/mockAll.js:48:5) at async Object.run (/snapshot/repo/build/node_modules/amplify-util-mock/lib/commands/mock/mock.js:19:3) at async Object.executeAmplifyCommand (/snapshot/repo/build/node_modules/amplify-util-mock/lib/amplify-plugin-index.js:47:3) at async executePluginModuleCommand (/snapshot/repo/build/node_modules/@aws-amplify/cli-internal/lib/execution-manager.js:142:5) at async executeCommand (/snapshot/repo/build/node_modules/@aws-amplify/cli-internal/lib/execution-manager.js:40:9) at async Object.run (/snapshot/repo/build/node_modules/@aws-amplify/cli-internal/lib/index.js:117:5) { classification: 'FAULT', options: { message: 'Failed to start API Mocking.. Reason: Callback must be a function. Received undefined', link: 'https://docs.amplify.aws/cli/graphql/troubleshooting/' }, downstreamException: undefined, toObject: [Function (anonymous)], details: undefined, resolution: undefined, code: undefined, link: 'https://docs.amplify.aws/cli/graphql/troubleshooting/' } 2023-02-08T12:37:27.570Z|info : amplify mock mock 2023-02-08T12:37:27.609Z|info : amplify-cli-core.banner-message/index.ts.fetch banner messages from https://aws-amplify.github.io/amplify-cli/banner-message.json({} ```

Additional information

No response

Before submitting, please confirm:

AnilMaktala commented 1 year ago

Hi @morepe 👋 , Thank you for raising the issue. I find problems with the name structure in the supplied schema. Please try the below-listed schema. I changed @hasmany to @hasmany and @hasmany to @Index.

type Variations @model @auth(rules: [{allow: public}]) {
id: ID!
displayName: String
productID: ID! @index(name: "byProduct")
}

type Store @model @auth(rules: [{allow: public}]) {
id: ID!
key: String!
displayName: String!
Products: [Product] @hasMany(indexName: "byStore", fields: ["id"])
}

type Product @model @auth(rules: [{allow: public}]) {
id: ID!
key: String!
displayName: String!
minimalPrice: Float!
storeID: ID! @index(name: "byStore")
Variations: [Variations] @hasMany(indexName: "byProduct", fields: ["id"])
}
image
morepe commented 1 year ago

Hi,

I just took the Schema that you provided, copied into my procjet and executed amplify build amplify mock

But I still got the same error:

grafik

Is there some kind cleanup or something I would need to perform? The schema looks straight forward to me.

AnilMaktala commented 1 year ago

@morepe, did you execute "amplify push" ? and try "amplify mock api".

morepe commented 1 year ago

No I did not do amplify push before. As I already added more models to my initial work and did not want to lose it, I tried the following:

Now the amplify mock works.

However, then I tried to add one more simple model (ProductCategories). It started to fail again with the same error and I can't make it work. So with the new model the schema now looks like this:

# This "input" configures a global authorization rule to enable public access to
# all models in this schema. Learn more about authorization rules here: https://docs.amplify.aws/cli/graphql/authorization-rules
input AMPLIFY { globalAuthRule: AuthRule = { allow: public } } # FOR TESTING ONLY!

type Variations @model @auth(rules: [{allow: public}]) {
id: ID!
displayName: String
productID: ID! @index(name: "byProduct")
}

type Store @model @auth(rules: [{allow: public}]) {
id: ID!
key: String!
displayName: String!
Products: [Product] @hasMany(indexName: "byStore", fields: ["id"])
}

type Product @model @auth(rules: [{allow: public}]) {
id: ID!
key: String!
displayName: String!
minimalPrice: Float!
storeID: ID! @index(name: "byStore")
Variations: [Variations] @hasMany(indexName: "byProduct", fields: ["id"])
productcategoriesID: ID! @index(name: "byProductCategories")
}

type ProductCategories @model @auth(rules: [{allow: public}]) {
  id: ID!
  key: String!
  displayName: String!
  Products: [Product] @hasMany(indexName: "byProductCategories", fields: ["id"])
}

The complete steps I did:

> amplify init

Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project test
The following configuration will be applied:

Project information
| Name: test
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: none
| Source Directory Path: src
| Distribution Directory Path: dist
| Build Command: npm run-script build
| Start Command: npm run-script start

> amplify add api

==> pastet graphgl content from https://github.com/aws-amplify/amplify-category-api/issues/1234#issuecomment-1422718374

> amplify mock

==> worked

> added product categories while mock was running

==> failed

Creating new table ProductCategoriesTable
Reloading failed with error
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function. Received undefined
GraphQL Schema change detected. Reloading...

> removed again

=> was working again

> amplify push

=> tried to add product categories again, did not work

> amplify push (now with product categories that did not work locally) 

=> same error still persists

Has it something to do with that the properties in the newly added model have the same name as onces in an existing model?

AnilMaktala commented 1 year ago

Hi @morepe, The issue has been reproduced, and it has been marked as a bug for the team to examine further. In the meantime, as a temporary solution you can try deleting the amplify/mock-data folder and let us know if that resolves the problem.

image
morepe commented 1 year ago

Thank you, deleting the amplify/mock-data works. However, its a bad workaround as I lose all my created testdata. So I am eagerly awaiting the bugfix :)

jonathantorrens commented 1 year ago

Hey, I believe I ran into something very similar, if not the same error. After forking the AmplifyCLI repo and building it in amplify-dev mode, I was able to track the issue down to what looks like a tiny error in the source code of the amplify-util-mock package. Specifically line 91 in the following file: /amplify-cli/packages/amplify-util-mock/lib/api/api.js

It's a very long if-statement:

if (((_a = appSyncConfig === null || appSyncConfig === void 0 ? void 0 : appSyncConfig.tables) === null || _a === void 0 ? void 0 : _a.some((table) => table === null || table === void 0 ? void 0 : table.isSearchable))  && !(0, amplify_cli_core_1.isWindowsPlatform)) {
              this.opensearchURL = await this.startOpensearchLocalServer(context, isLocalDBEmpty);
}

The if statement seems to have extraneous parentheses after this property: .isWindowsPlatform()

After removing them, the mock API built just fine. I've committed the changes locally but I'm not sure how to put in a pull request. This is the TypeScript file visible in the published GitHub repo: https://github.com/aws-amplify/amplify-cli/blob/dev/packages/amplify-util-mock/src/api/api.ts

Would love to hear if anyone else can verify.