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

Viewed 428

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?

1 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.

Related