#Cannot find package '$amplify' imported from .../amplify/functions/myFunction/myFunctionHandler.ts

1 messages · Page 1 of 1 (latest)

neat crypt
#

I'm trying to create a Lambda function, but I'm getting subject error message when I try to run Sandbox or Deploy. My amplify/tsconfig looks like this:

"compilerOptions": { "target": "es2022", "module": "es2022", "moduleResolution": "bundler", "resolveJsonModule": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, "paths": { "$amplify/*": ["../.amplify/generated/*"], "@/*": ["./*"] } }

My root/tsconfig has this line:

"exclude": ["node_modules", "amplify", "amplify/**/*"]

The culprit is import { env } from '$amplify/env/myFunction';

It seems to me that the amplify files are not being generated when running sandbox or deploying. Is this something I have to trigger manually? Thanks!

bright marsh
#

hey the env files get generated on each deploy. I would ensure the import is referring to the correct function name if you are using the name property. The other may be you have not attached this function in the backend.ts defineBackend definition or in other resources such as data or auth.

neat crypt
#

@bright marsh Thanks for your response. The function names are correct; whether I use the "name" property or not has no impact

`export const myFunctionFnDef = defineFunction({
    entry: './myFunctionHandler.ts',
    // name: 'myFunction', // does not make a difference
    timeoutSeconds: 200,
    memoryMB: 512, // 1024
    runtime: 20, // Node version
});

export const myFunction = a
    .query()
    .arguments({ verbose: a.boolean() })
    .authorization(allow => [allow.authenticated()]) 
    .handler(a.handler.function(myFunctionFnDef).async());`

I'm adding "myFunction" to the schema and myFunctionFnDef for authorization:

.authorization(allow => [ allow.resource(freshStartFnDef).to(['query', 'listen', 'mutate']), allow.resource(weatherFnDef).to(['query', 'listen', 'mutate']), ]);

I actually have 2 lambdas. The first I created a few months ago and it does not cause an issue. The second (myFunction) , which I just added, creates the issue. If I had to guess I'd say it's a chicken-egg thing where amplify will not create the needed files because the code does not compile ($amplify/env/myFunction is missing) and the code does not compile because the $amplify files are not in place.

Also, doesn't "Cannot find package '$amplify'" perhaps imply an issue with my tsconfig? why can't it resolve $amplify? (my other Lambda does not use $amplify; it accesses process.env directly)

Lastly, I have my functions in the functions folder; should they be in the data folder?

neat crypt
#

I got this to work. tsconfig was fine. To answer my own questions: the function can be in the functions folder, but the function meta data (defFunction, a....) need to be in the data folder. Moving those eliminated the errror

hollow hearth
#

If I may ask, why are you doing it this way round? Why aren't you adding the Auth to the lambda inside the lambda resource using backend.data?

#

I would have thought creating the Data stack and then defining the Auth of a resource inside that stack would create some circular dependency issues

neat crypt
#

I put the function definition and auth in the function folders because the way I looked at it they belonged together and so I had everything in one place, but this caused (I think) circularity preventing the creation of the $amplify files. So now I have a file in my data folder where I do all the function defs and auth and then I pull that into the schema like this:

`import { function1, function1Handler, function2, function2Handler } from './function-def';

const schema = a
.schema({
// ... other schema stuff
function1,
function2,
})
.authorization(allow => [
allow.resource(function1Handler).to(['query', 'listen', 'mutate']),
allow.resource(function2Handler).to(['query', 'listen', 'mutate']),
]);`

where function1Handler is:

export const function1Handler = defineFunction({ entry: '../functions/function1/handler.ts', name: 'function1', timeoutSeconds: 200, memoryMB: 512, // 1024 runtime: 20, // Node version });

and function1 is:

export const function1 = a .query() .arguments({ verbose: a.boolean() }) .authorization(allow => [allow.authenticated()]) .handler(a.handler.function(function1Handler).async());

I do not export anything from my functions folder (other than obviously the handlers)

hollow hearth
#

I would personally move giving Auth to resources out of the data stack so that the data stack isn't dependent on them

neat crypt
#

sorry i'm new to this. You would add it to the schema in the backend file after the schema is created?

hollow hearth
#

So I create a new stack for each of my functionalities and put my lambdas inside those stacks, then I access the data permissions using backend.data.resources.graphqlApi.grant...()

#

So the Data stack gets created first and added to the backend object which can then be passed to your other stacks