Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@contentlayer/cli/src/commands/BuildCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class BuildCommand extends BaseCommand {
executeSafe = () =>
pipe(
this.clearCacheIfNeeded(),
T.chain(() => core.getConfig({ configPath: this.configPath })),
T.chain(() => core.getConfig({ configPath: this.configPath, esbuildOptions: { external: this.external } })),
T.tap((config) => (config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig))),
T.chain((config) => core.generateDotpkg({ config, verbose: this.verbose })),
T.tap(core.logGenerateInfo),
Expand Down
2 changes: 1 addition & 1 deletion packages/@contentlayer/cli/src/commands/DevCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class DevCommand extends BaseCommand {
executeSafe = () =>
pipe(
S.fromEffect(this.clearCacheIfNeeded()),
S.chain(() => core.getConfigWatch({ configPath: this.configPath })),
S.chain(() => core.getConfigWatch({ configPath: this.configPath, esbuildOptions: { external: this.external } })),
S.tapSkipFirstRight(() => T.log(`Contentlayer config change detected. Updating type definitions and data...`)),
S.tapRight((config) =>
config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig),
Expand Down
16 changes: 11 additions & 5 deletions packages/@contentlayer/cli/src/commands/PostInstallCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ export class PostInstallCommand extends BaseCommand {
static paths = [['postinstall']]

executeSafe = () => {
const { configPath } = this
const { configPath, external } = this
return pipe(
T.gen(function* ($) {
const artifactsDirPath = yield* $(core.ArtifactsDir.mkdir)

yield* $(generateTypes({ artifactsDirPath, moduleName: 'generated', configPath }))
yield* $(
generateTypes({
artifactsDirPath,
moduleName: 'generated',
configOptions: { configPath, esbuildOptions: { external } },
}),
)

yield* $(addToplevelDotpkgToGitignore())
}),
Expand All @@ -30,11 +36,11 @@ export class PostInstallCommand extends BaseCommand {
const generateTypes = ({
artifactsDirPath,
moduleName,
configPath,
configOptions,
}: {
artifactsDirPath: string
moduleName: string
configPath?: string
configOptions: Parameters<typeof core.getConfig>[0]
}) =>
T.gen(function* ($) {
const dirPath = path.join(artifactsDirPath, moduleName)
Expand All @@ -51,7 +57,7 @@ const generateTypes = ({

if (indexDtsFileExists && typesDtsFileExists) return

const sourceEither = yield* $(pipe(core.getConfig({ configPath }), T.either))
const sourceEither = yield* $(pipe(core.getConfig(configOptions), T.either))
if (sourceEither._tag === 'Left') {
if (sourceEither.left._tag === 'NoConfigFoundError') {
yield* $(fs.writeFile(indexDtsFilePath, moduleStubFileIndexDts))
Expand Down
6 changes: 6 additions & 0 deletions packages/@contentlayer/cli/src/commands/_BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export abstract class BaseCommand extends Command {
description: 'More verbose logging and error stack traces',
})

external = Option.String('--external', {
description: 'External dependencies to exclude from the config bundle',
validator: t.isArray(t.isString()),
required: false,
})

abstract executeSafe: () => T.Effect<OT.HasTracer & HasClock & HasCwd & HasConsole & fs.HasFs, unknown, void>

execute = (): Promise<void> =>
Expand Down
1 change: 1 addition & 0 deletions packages/@contentlayer/core/src/getConfig/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export abstract class EsbuildWatcher {

export type BuildResult = esbuild.BuildResult
export type Plugin = esbuild.Plugin
export type BuildOptions = esbuild.BuildOptions

export type EsbuildError = UnknownEsbuildError | KnownEsbuildError

Expand Down
7 changes: 6 additions & 1 deletion packages/@contentlayer/core/src/getConfig/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ export type Config = {

export const getConfig = ({
configPath,
esbuildOptions,
}: {
/** Contentlayer config source path */
configPath?: string
esbuildOptions?: esbuild.BuildOptions
}): T.Effect<OT.HasTracer & HasCwd & fs.HasFs, GetConfigError, Config> =>
pipe(
getConfigWatch({ configPath }),
getConfigWatch({ configPath, esbuildOptions }),
S.take(1),
S.runCollect,
T.map(Chunk.unsafeHead),
Expand All @@ -49,8 +51,10 @@ export const getConfig = ({

export const getConfigWatch = ({
configPath: configPath_,
esbuildOptions,
}: {
configPath?: string
esbuildOptions?: esbuild.BuildOptions
}): S.Stream<OT.HasTracer & HasCwd & fs.HasFs, never, E.Either<GetConfigError, Config>> => {
const resolveParams = pipe(
T.structPar({
Expand All @@ -66,6 +70,7 @@ export const getConfigWatch = ({
S.chainMapEitherRight(({ configPath, outfilePath, cwd }) =>
pipe(
esbuild.makeAndSubscribe({
...esbuildOptions,
entryPoints: [configPath],
entryNames: '[name]-[hash]',
outfile: outfilePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export class DefaultCommand extends Command {
validator: t.isString(),
})

external = Option.String('--external', {
description: 'External dependencies to exclude from the config bundle',
validator: t.isArray(t.isString()),
required: false,
})

// TODO refactor similar to `@contentlayer2/cli`
async execute() {
try {
Expand All @@ -55,7 +61,7 @@ export class DefaultCommand extends Command {

executeSafe = (): T.Effect<OT.HasTracer & HasCwd & HasConsole & fs.HasFs, unknown, void> =>
pipe(
getConfig({ configPath: this.configPath }),
getConfig({ configPath: this.configPath, esbuildOptions: { external: this.external } }),
T.chain((config) =>
T.struct({ source: T.succeed(config.source), schema: config.source.provideSchema(config.esbuildHash) }),
),
Expand Down
16 changes: 9 additions & 7 deletions packages/next-contentlayer/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ import '@contentlayer2/utils/effect/Tracing/Enable'
import * as core from '@contentlayer2/core'
import { errorToString } from '@contentlayer2/utils'
import { E, OT, pipe, S, T } from '@contentlayer2/utils/effect'
import type * as esbuild from 'esbuild'
import type { WebpackOptionsNormalized } from 'webpack'

import { checkConstraints } from './check-constraints.js'

export type NextPluginOptions = {
configPath?: string | undefined
esbuildOptions?: Pick<esbuild.BuildOptions, 'external'> | undefined
}

/** Seems like the next.config.js export function might be executed multiple times, so we need to make sure we only run it once */
let contentlayerInitialized = false

const runContentlayerDev = async ({ configPath }: NextPluginOptions) => {
const runContentlayerDev = async ({ configPath, esbuildOptions }: NextPluginOptions) => {
if (contentlayerInitialized) return
contentlayerInitialized = true

await pipe(
core.getConfigWatch({ configPath }),
core.getConfigWatch({ configPath, esbuildOptions }),
S.tapSkipFirstRight(() => T.log(`Contentlayer config change detected. Updating type definitions and data...`)),
S.tapRight((config) => (config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig))),
S.chainSwitchMapEitherRight((config) => core.generateDotpkgStream({ config, verbose: false, isDev: true })),
Expand All @@ -29,12 +31,12 @@ const runContentlayerDev = async ({ configPath }: NextPluginOptions) => {
)
}

const runContentlayerBuild = async ({ configPath }: NextPluginOptions) => {
const runContentlayerBuild = async ({ configPath, esbuildOptions }: NextPluginOptions) => {
if (contentlayerInitialized) return
contentlayerInitialized = true

await pipe(
core.getConfig({ configPath }),
core.getConfig({ configPath, esbuildOptions }),
T.chain((config) => core.generateDotpkg({ config, verbose: false })),
T.tap(core.logGenerateInfo),
OT.withSpan('next-contentlayer:runContentlayerBuild'),
Expand All @@ -56,14 +58,14 @@ export const runBeforeWebpackCompile = async ({
const isNextDev = mode === 'development'
const isBuild = mode === 'production'

const { configPath } = pluginOptions
const { configPath, esbuildOptions } = pluginOptions

if (isBuild) {
checkConstraints()
await runContentlayerBuild({ configPath })
await runContentlayerBuild({ configPath, esbuildOptions })
} else if (isNextDev && !devServerStartedRef.current) {
devServerStartedRef.current = true
// TODO also block here until first Contentlayer run is complete
runContentlayerDev({ configPath })
runContentlayerDev({ configPath, esbuildOptions })
}
}