Skip to content

Commit

Permalink
fix: use the right Blobs context in serve (#6507)
Browse files Browse the repository at this point in the history
* fix: use the right Blobs context in `serve`

* refactor: remove unnecessary function
  • Loading branch information
eduardoboucas committed Apr 10, 2024
1 parent 1908078 commit a3ff3c6
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/commands/dev/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import process from 'process'
import { applyMutations } from '@netlify/config'
import { OptionValues, Option } from 'commander'

import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContext } from '../../lib/blobs/blobs.js'
import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContextWithEdgeAccess } from '../../lib/blobs/blobs.js'
import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js'
import { startFunctionsServer } from '../../lib/functions/server.js'
import { printBanner } from '../../utils/banner.js'
Expand Down Expand Up @@ -107,7 +107,7 @@ export const dev = async (options: OptionValues, command: BaseCommand) => {

env.NETLIFY_DEV = { sources: ['internal'], value: 'true' }

const blobsContext = await getBlobsContext({
const blobsContext = await getBlobsContextWithEdgeAccess({
debug: options.debug,
projectRoot: command.workingDir,
siteID: site.id ?? UNLINKED_SITE_MOCK_ID,
Expand Down
4 changes: 2 additions & 2 deletions src/commands/functions/functions-serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { join } from 'path'

import { OptionValues } from 'commander'

import { getBlobsContext } from '../../lib/blobs/blobs.js'
import { getBlobsContextWithEdgeAccess } from '../../lib/blobs/blobs.js'
import { startFunctionsServer } from '../../lib/functions/server.js'
import { printBanner } from '../../utils/banner.js'
import {
Expand Down Expand Up @@ -42,7 +42,7 @@ export const functionsServe = async (options: OptionValues, command: BaseCommand
errorMessage: 'Could not acquire configured functions port',
})

const blobsContext = await getBlobsContext({
const blobsContext = await getBlobsContextWithEdgeAccess({
debug: options.debug,
projectRoot: command.workingDir,
siteID: site.id ?? UNLINKED_SITE_MOCK_ID,
Expand Down
25 changes: 20 additions & 5 deletions src/commands/serve/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import process from 'process'

import { OptionValues } from 'commander'

import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContext } from '../../lib/blobs/blobs.js'
import {
BLOBS_CONTEXT_VARIABLE,
encodeBlobsContext,
getBlobsContextWithAPIAccess,
getBlobsContextWithEdgeAccess,
} from '../../lib/blobs/blobs.js'
import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js'
import { startFunctionsServer } from '../../lib/functions/server.js'
import { printBanner } from '../../utils/banner.js'
Expand Down Expand Up @@ -92,22 +97,31 @@ export const serve = async (options: OptionValues, command: BaseCommand) => {
`${NETLIFYDEVWARN} Changes will not be hot-reloaded, so if you need to rebuild your site you must exit and run 'netlify serve' again`,
)

const blobsContext = await getBlobsContext({
const blobsOptions = {
debug: options.debug,
projectRoot: command.workingDir,
siteID: site.id ?? UNLINKED_SITE_MOCK_ID,
})
}

process.env[BLOBS_CONTEXT_VARIABLE] = encodeBlobsContext(blobsContext)
// We start by running a build, so we want a Blobs context with API access,
// which is what build plugins use.
process.env[BLOBS_CONTEXT_VARIABLE] = encodeBlobsContext(await getBlobsContextWithAPIAccess(blobsOptions))

const { configPath: configPathOverride } = await runBuildTimeline({
command,
settings,
options,
env: {},
})

// Now we generate a second Blobs context object, this time with edge access
// for runtime access (i.e. from functions and edge functions).
const runtimeBlobsContext = await getBlobsContextWithEdgeAccess(blobsOptions)

process.env[BLOBS_CONTEXT_VARIABLE] = encodeBlobsContext(runtimeBlobsContext)

const functionsRegistry = await startFunctionsServer({
blobsContext,
blobsContext: runtimeBlobsContext,
command,
config,
debug: options.debug,
Expand Down Expand Up @@ -143,6 +157,7 @@ export const serve = async (options: OptionValues, command: BaseCommand) => {
const inspectSettings = generateInspectSettings(options.edgeInspect, options.edgeInspectBrk)
const url = await startProxyServer({
addonsUrls,
blobsContext: runtimeBlobsContext,
command,
config,
configPath: configPathOverride,
Expand Down
57 changes: 43 additions & 14 deletions src/lib/blobs/blobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,27 @@ import { v4 as uuidv4 } from 'uuid'
import { log, NETLIFYDEVLOG } from '../../utils/command-helpers.js'
import { getPathInProject } from '../settings.js'

let hasPrintedLocalBlobsNotice = false

export const BLOBS_CONTEXT_VARIABLE = 'NETLIFY_BLOBS_CONTEXT'

export interface BlobsContext {
interface BaseBlobsContext {
deployID: string
edgeURL: string
siteID: string
token: string
}

export interface BlobsContextWithAPIAccess extends BaseBlobsContext {
apiURL: string
}

export interface BlobsContextWithEdgeAccess extends BaseBlobsContext {
edgeURL: string
uncachedEdgeURL: string
}

export type BlobsContext = BlobsContextWithAPIAccess | BlobsContextWithEdgeAccess

let hasPrintedLocalBlobsNotice = false

export const BLOBS_CONTEXT_VARIABLE = 'NETLIFY_BLOBS_CONTEXT'

const printLocalBlobsNotice = () => {
if (hasPrintedLocalBlobsNotice) {
return
Expand All @@ -31,7 +40,12 @@ const printLocalBlobsNotice = () => {
)
}

const startBlobsServer = async (debug: boolean, projectRoot: string, token: string) => {
/**
* Starts a local Blobs server on a random port and generates a random token
* for its authentication.
*/
const initializeBlobsServer = async (projectRoot: string, debug: boolean) => {
const token = uuidv4()
const directory = path.resolve(projectRoot, getPathInProject(['blobs-serve']))
const server = new BlobsServer({
debug,
Expand All @@ -42,8 +56,9 @@ const startBlobsServer = async (debug: boolean, projectRoot: string, token: stri
token,
})
const { port } = await server.start()
const url = `http://localhost:${port}`

return { port }
return { url, token }
}

interface GetBlobsContextOptions {
Expand All @@ -52,15 +67,29 @@ interface GetBlobsContextOptions {
siteID: string
}

/**
* Starts a local Blobs server and returns a context object that lets build
* plugins connect to it.
*/
export const getBlobsContextWithAPIAccess = async ({ debug, projectRoot, siteID }: GetBlobsContextOptions) => {
const { token, url } = await initializeBlobsServer(projectRoot, debug)
const context: BlobsContextWithAPIAccess = {
apiURL: url,
deployID: '0',
siteID,
token,
}

return context
}

/**
* Starts a local Blobs server and returns a context object that lets functions
* connect to it.
* and edge functions connect to it.
*/
export const getBlobsContext = async ({ debug, projectRoot, siteID }: GetBlobsContextOptions) => {
const token = uuidv4()
const { port } = await startBlobsServer(debug, projectRoot, token)
const url = `http://localhost:${port}`
const context: BlobsContext = {
export const getBlobsContextWithEdgeAccess = async ({ debug, projectRoot, siteID }: GetBlobsContextOptions) => {
const { token, url } = await initializeBlobsServer(projectRoot, debug)
const context: BlobsContextWithEdgeAccess = {
deployID: '0',
edgeURL: url,
siteID,
Expand Down
4 changes: 2 additions & 2 deletions src/lib/edge-functions/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import BaseCommand from '../../commands/base-command.js'
import { $TSFixMe } from '../../commands/types.js'
import { NETLIFYDEVERR, chalk, error as printError } from '../../utils/command-helpers.js'
import { FeatureFlags, getFeatureFlagsFromSiteInfo } from '../../utils/feature-flags.js'
import { BlobsContext } from '../blobs/blobs.js'
import { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'
import { getGeoLocation } from '../geo-location.js'
import { getPathInProject } from '../settings.js'
import { startSpinner, stopSpinner } from '../spinner.js'
Expand Down Expand Up @@ -94,7 +94,7 @@ export const initializeProxy = async ({
state,
}: {
accountId: string
blobsContext: BlobsContext
blobsContext: BlobsContextWithEdgeAccess
command: BaseCommand
config: $TSFixMe
configPath: string
Expand Down
4 changes: 2 additions & 2 deletions src/lib/functions/netlify-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import semver from 'semver'

import { error as errorExit } from '../../utils/command-helpers.js'
import { BACKGROUND } from '../../utils/functions/get-functions.js'
import type { BlobsContext } from '../blobs/blobs.js'
import type { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'

const TYPESCRIPT_EXTENSIONS = new Set(['.cts', '.mts', '.ts'])
const V2_MIN_NODE_VERSION = '18.14.0'
Expand All @@ -34,7 +34,7 @@ export default class NetlifyFunction {

private readonly directory: string
private readonly projectRoot: string
private readonly blobsContext: BlobsContext
private readonly blobsContext: BlobsContextWithEdgeAccess
private readonly timeoutBackground: number
private readonly timeoutSynchronous: number

Expand Down
4 changes: 2 additions & 2 deletions src/utils/proxy-server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BaseCommand from '../commands/base-command.js'
import { $TSFixMe, NetlifyOptions } from '../commands/types.js'
import { BlobsContext } from '../lib/blobs/blobs.js'
import { BlobsContextWithEdgeAccess } from '../lib/blobs/blobs.js'
import { FunctionsRegistry } from '../lib/functions/registry.js'

import { exit, log, NETLIFYDEVERR } from './command-helpers.js'
Expand Down Expand Up @@ -64,7 +64,7 @@ export const startProxyServer = async ({
}: {
accountId: string
addonsUrls: $TSFixMe
blobsContext?: BlobsContext
blobsContext?: BlobsContextWithEdgeAccess
command: BaseCommand
config: NetlifyOptions['config']
// An override for the Netlify config path
Expand Down
11 changes: 4 additions & 7 deletions src/utils/run-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,8 @@ export const runNetlifyBuild = async ({
return { configMutations }
}

export const runDevTimeline = (options: Omit<Parameters<typeof runNetlifyBuild>[0], 'timeline'>) =>
runNetlifyBuild({ ...options, timeline: 'dev' })
type RunTimelineOptions = Omit<Parameters<typeof runNetlifyBuild>[0], 'timeline'>

/**
* @param {Omit<Parameters<typeof runNetlifyBuild>[0], 'timeline'>} options
*/
// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type.
export const runBuildTimeline = (options) => runNetlifyBuild({ ...options, timeline: 'build' })
export const runDevTimeline = (options: RunTimelineOptions) => runNetlifyBuild({ ...options, timeline: 'dev' })

export const runBuildTimeline = (options: RunTimelineOptions) => runNetlifyBuild({ ...options, timeline: 'build' })

2 comments on commit a3ff3c6

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Benchmark results

  • Dependency count: 1,313
  • Package size: 294 MB
  • Number of ts-expect-error directives: 1,007

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📊 Benchmark results

  • Dependency count: 1,313
  • Package size: 294 MB
  • Number of ts-expect-error directives: 1,007

Please sign in to comment.