Skip to content

Commit

Permalink
feat: automatic create tsconfig for editor support on functions
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasholzer committed Oct 16, 2023
1 parent 2a68876 commit 631e53c
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 6 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/commands/functions/functions-create.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import fetch from 'node-fetch'
import ora from 'ora'

import { fileExistsAsync } from '../../lib/fs.mjs'
import { checkTsconfigForV2Api } from '../../lib/functions/check-tsconfig-for-v2-api.mjs'
import { getAddons, getCurrentAddon, getSiteData } from '../../utils/addons/prepare.mjs'
import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, error, log } from '../../utils/command-helpers.mjs'
import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.mjs'
Expand Down Expand Up @@ -715,6 +716,10 @@ const functionsCreate = async (name, options, command) => {
const functionsDir =
functionType === 'edge' ? await ensureEdgeFuncDirExists(command) : await ensureFunctionDirExists(command)

if (functionType === 'serverless') {
await checkTsconfigForV2Api({ functionsDir })
}

/* either download from URL or scaffold from template */
const mainFunc = options.url ? downloadFromURL : scaffoldFromTemplate
await mainFunc(command, options, name, functionsDir, functionType)
Expand Down
62 changes: 62 additions & 0 deletions src/lib/functions/check-tsconfig-for-v2-api.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// @ts-check
import { existsSync } from 'fs'
import { writeFile } from 'fs/promises'
import { createRequire } from 'module'
import { join } from 'path'

import { NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, log } from '../../utils/command-helpers.mjs'

/**
* The `tsconfig.json` we are going to write to the functions directory.
* We use a template string instead of JSON.stringify to be able to add comments to the JSON.
* Comments inside the JSON are accepted by TypeScript and tsconfig.
*/
const TSCONFIG_TMPL = `{
// "extends": "../tsconfig.json", /** If you want to share configuration enable the extends property (like strict: true) */
"compilerOptions": {
"noEmit": true /** This tsconfig.json is only used for type checking and editor support */,
"module": "ESNext",
"moduleResolution": "Bundler" /** This is needed to use .ts file extensions as we bundle it */,
"allowImportingTsExtensions": true /** This allows using .ts file extension instead of the standard .js extension. We allow this for better compatibility with Deno Edge Functions */,
"checkJs": true /** Enable type checking in JavaScript files as well */,
"allowJs": true /** Make JavaScript files part of the program as well */
}
}
`

/**
* Function that is responsible for validating the typescript configuration for serverless functions.
* It validates the `tsconfig.json` settings and if they don't comply it will throw an error.
* @param {object} config
* @param {string|undefined} config.functionsDir An absolute path to the functions directory
*/
export async function checkTsconfigForV2Api(config) {
// if no functionsDir is specified or the dir does not exist just return
if (!config.functionsDir || !existsSync(config.functionsDir)) {
return
}

try {
const require = createRequire(config.functionsDir)
require.resolve('@netlify/functions')
} catch {
log(
`${NETLIFYDEVWARN} Please install the ${chalk.dim(
'@netlify/functions',
)} package to get a better typed experience!`,
)
}
const tsconfig = join(config.functionsDir, 'tsconfig.json')

if (existsSync(tsconfig)) {
return
}

await writeFile(tsconfig, TSCONFIG_TMPL, 'utf-8')

log(
`${NETLIFYDEVLOG} Successfully created a ${chalk.dim(
'tsconfig.json',
)} file in your functions folder for better Editor support!`,
)
}
9 changes: 9 additions & 0 deletions src/lib/functions/netlify-function.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import semver from 'semver'
import { error as errorExit } from '../../utils/command-helpers.mjs'
import { BACKGROUND } from '../../utils/functions/get-functions.mjs'

import { checkTsconfigForV2Api } from './check-tsconfig-for-v2-api.mjs'

const TYPESCRIPT_EXTENSIONS = new Set(['.cts', '.mts', '.ts'])
const V2_MIN_NODE_VERSION = '18.0.0'

Expand Down Expand Up @@ -138,6 +140,13 @@ export default class NetlifyFunction {

try {
const { includedFiles = [], schedule, srcFiles, ...buildData } = await this.buildQueue

if (buildData.runtimeAPIVersion === 2) {
// Check f the tsconfig.json file exists for the editor support.
// If not create it
await checkTsconfigForV2Api({ functionsDir: this.directory })
}

const srcFilesSet = new Set(srcFiles)
const srcFilesDiff = this.getSrcFilesDiff(srcFilesSet)

Expand Down

0 comments on commit 631e53c

Please sign in to comment.