Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to build a Firebase functions project while importing types from an outer project (one level up). Losing folder structure after `tsc` compiles

Sorry in advance for the long question, but project structure issues/bugs are kind of hard to explain.

I have a Next.js project, which is my root project. It's a Typescript project so it has its own tsconfig.json

Here is the basic structure:

> app    // APP COMPONENTS
> pages  // NEXT.JS PAGES
> types  // SOME GLOBAL TYPES FOR THE PROJECT
firebase.json
firestore.rules
storage.rules
tsconfig.json

I need to add cloud functions to this project. So I've followed the docs on:

https://firebase.google.com/docs/functions/typescript

Basically I've typed firebase init functions and followed the instructions from the CLI.

It then created a functions as following (the > sign is denoting a folder):

> app

> functions  // NEW FOLDER FOR THE FUNCTIONS PROJECT
  > src
    index.ts
  package.json
  tsconfig.json

> pages
> types
firebase.json
firestore.rules
package.json
storage.rules
tsconfig.json

See now that the functions folder has its own tsconfig.json file and its own package.json file. In essence, it is a project of its own. I'm fine with that idea.

Here is the tsconfig.json file that was created:

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "es2017"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

It also adds a predeploy hook to my firebase.json file.

"functions": {
  "predeploy": "npm --prefix \"$RESOURCE_DIR\" run build"
}

This is necessary to build the .ts file before deployment. It will build the files on the functions/src folder to the functions/lib folder, as per the tsconfig.json.

The basic helloWorld example builds and deploys just fine. I've added some files to the functions folder and its all working.

See my files on functions/src:

enter image description here

See the compiled files on functions/lib:

enter image description here

It's the very same structure and files, just as you'd expect.

THE PROBLEM

The problem begins when I'm importing a type from the "outer" root project. For example:

I go on functions/src/index.ts and do something like the following:

import SomeType from "../../types/whatever"

// USE THE TYPE HERE

Now see what the build result is (i.e: the functions/lib folder):

enter image description here

Now it basically creates another functions under the lib folder. And it also basically copies the files from my types folder. I have no idea why it is doing that.

I wasn't expecting that at all. I'd like to use my types from the outer root project, but without messing with the structure of the resulting functions/lib folder.

What could be happening?

like image 236
cbdeveloper Avatar asked Oct 14 '25 16:10

cbdeveloper


2 Answers

A way around it, that is not too hacky, is to declare your shared type as a namespace and import them with a /// <reference path="..."> command.

That way, you will be able to access your type through the declared namespace and the build will keep the required directory structure.

Assuming the following project

my-project/
  functions/
    src/
      index.ts
  shared/
    type.d.ts
  ...otherFiles

shared.ts

declare namespace shared {
  interface IType {
    name: string
  }
}

index.ts

// eslint-disable-next-line
/// <reference path="../../shared/model.d.ts" /> 
import * as functions from "firebase-functions";

export const helloWorld = functions.https.onRequest((request, response) => {
  const type:shared.IType = {name: "John"};
  functions.logger.info("Hello logs!", {structuredData: true});
  response.send(`Hello ${type.name}!`);
});

The // eslint-disable-next-line comments is required if you use eslint default rules from firebase template because of the @typescript-eslint/triple-slash-reference rules.

like image 57
mxp-qk Avatar answered Oct 17 '25 07:10

mxp-qk


I just solved a similar issue where I wanted to import the types from the project folder into the firebase functions folder.

// Default folder structure for Next.js and firebase functions
project-folder/
├── functions/
│   ├── src/
│   │   ├── index.ts
│   │   └── interfaces.ts // (See explanation for this one)
│   ├── package.json
│   └── tsconfig.json
├── interfaces/
│   └── index.ts
├── lib/
├── pages/
│   ├── _app.tsx
│   └── index.tsx
├── package.json
└── tsconfig.json

The functions/src/interfaces.ts simply exports the types from the project folder, like so:

export * from "../../interfaces";

If you run tsc in the functions-folder now, it will generate a file structure that looks different from before:

// Output when not importing from outside functions src folder
lib/
├── index.js
└── index.js.map

// Output when importing interfaces from outside src folder
lib/
├── functions/
│   └── src/
│       ├── index.js
│       └── index.js.map
└── interfaces/

All you now have to do is change package.json a little bit:

{
  "main": "lib/functions/src/index.js"
}

That's it! Files in your functions folder can import from the project folder.

Note about interfaces.ts: I added this file because it seemed cleaner to have only one file that imports from outside the functions folder. Also, this way importing interfaces in the functions folder is similar to everywhere else in the project.

like image 25
Marius Brataas Avatar answered Oct 17 '25 06:10

Marius Brataas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!