Skip to content

feat(contentlayer): use provideSchema as Stream #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion examples/node-script-notion/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"name": "node-script-notion-example",
"private": true,
"scripts": {
"start": "contentlayer build && node --experimental-json-modules my-script.mjs"
"start": "contentlayer build && node --experimental-json-modules my-script.mjs",
"dev": "contentlayer dev"
},
"dependencies": {
"@notionhq/client": "^2.2.3",
Expand Down
5 changes: 3 additions & 2 deletions packages/@contentlayer/cli/src/commands/PostInstallCommand.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as path from 'node:path'
import { config } from 'node:process'

import * as core from '@contentlayer/core'
import { fs } from '@contentlayer/utils'
import { OT, pipe, T } from '@contentlayer/utils/effect'
import { O, OT, pipe, S, T } from '@contentlayer/utils/effect'

import { BaseCommand } from './_BaseCommand.js'

Expand Down Expand Up @@ -60,7 +61,7 @@ const generateTypes = ({
}

const { source, esbuildHash } = sourceEither.right
const schemaDef = yield* $(source.provideSchema(esbuildHash))
const schemaDef = yield* $(pipe(source.provideSchema(esbuildHash), S.runHead, T.map(O.getUnsafe)))

if (!indexDtsFileExists) {
const options = source.options
Expand Down
2 changes: 1 addition & 1 deletion packages/@contentlayer/core/src/dynamic-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const dynamicBuild = ({ config, verbose }: { config: Config; verbose: boo
pipe(
T.gen(function* ($) {
// TODO try to do this as generation-time in the future and come up with a serialization strategy for the `schemaDef`
const schemaDef = yield* $(config.source.provideSchema(config.esbuildHash))
const schemaDef = yield* $(pipe(config.source.provideSchema(config.esbuildHash), S.runHead, T.map(O.getUnsafe)))

const cache = yield* $(
pipe(
Expand Down
22 changes: 14 additions & 8 deletions packages/@contentlayer/core/src/generation/generate-dotpkg.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AbsolutePosixFilePath, RelativePosixFilePath } from '@contentlayer/utils'
import { filePathJoin, fs, relative } from '@contentlayer/utils'
import type { E, HasClock, HasConsole } from '@contentlayer/utils/effect'
import { Array, Chunk, flow, OT, pipe, S, T } from '@contentlayer/utils/effect'
import { Array, Chunk, flow, OT, pipe, S, T, Tp } from '@contentlayer/utils/effect'
import type { GetContentlayerVersionError } from '@contentlayer/utils/node'
import { getContentlayerVersion } from '@contentlayer/utils/node'
import { camelCase } from 'camel-case'
Expand Down Expand Up @@ -82,20 +82,26 @@ export const generateDotpkgStream = ({
> => {
const writtenFilesCache = {}
const generationOptions = { sourcePluginType: config.source.type, options: config.source.options }
const resolveParams = pipe(
T.structPar({
schemaDef: config.source.provideSchema(config.esbuildHash),
targetPath: ArtifactsDir.mkdir,
}),
T.either,

const provideSchema = pipe(
config.source.provideSchema(config.esbuildHash),
S.mapEffect((schemaDef) =>
pipe(
T.structPar({
schemaDef: T.succeed(schemaDef),
targetPath: ArtifactsDir.mkdir,
}),
),
),
S.either,
)

// .pipe(
// tap((artifactsDir) => watchData && errorIfArtifactsDirIsDeleted({ artifactsDir }))
// ),

return pipe(
S.fromEffect(resolveParams),
provideSchema,
S.chainMapEitherRight(({ schemaDef, targetPath }) =>
pipe(
config.source.fetchData({ schemaDef, verbose }),
Expand Down
2 changes: 1 addition & 1 deletion packages/@contentlayer/core/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export type SourcePlugin = {

export type ProvideSchema = (
esbuildHash: string,
) => T.Effect<OT.HasTracer & HasConsole, SourceProvideSchemaError, SchemaDef>
) => S.Stream<OT.HasTracer & HasClock & HasConsole, SourceProvideSchemaError, SchemaDef>
export type FetchData = (_: {
schemaDef: SchemaDef
verbose: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url'
import * as SourceFiles from '@contentlayer/source-files'
import { provideDummyTracing } from '@contentlayer/utils'
import type { HasClock, HasConsole, OT } from '@contentlayer/utils/effect'
import { pipe, provideTestConsole, T } from '@contentlayer/utils/effect'
import { O, pipe, provideTestConsole, S, T } from '@contentlayer/utils/effect'
import * as Stackbit from '@stackbit/sdk'
import { expect, test } from 'vitest'

Expand Down Expand Up @@ -36,7 +36,7 @@ const schemaFromFixture = (fixtureName: string) => async () => {
const documentTypes = stackbitConfigToDocumentTypes(configResult.config!)

const contentlayerSource = await SourceFiles.makeSource({ contentDirPath: NOT_USED_STR, documentTypes })(undefined)
const schema = await runMain(contentlayerSource.provideSchema(NOT_USED_STR))
const schema = await runMain(pipe(contentlayerSource.provideSchema(NOT_USED_STR), S.runHead, T.map(O.getUnsafe)))

return schema.result
}
Expand Down
2 changes: 1 addition & 1 deletion packages/@contentlayer/source-contentful/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const makeSourcePlugin: core.MakeSourcePlugin<Args & PluginOptions> = (ar
type: 'contentful',
extensions,
options,
provideSchema: () => provideSchema({ accessToken, spaceId, environmentId, options, schemaOverrides }),
provideSchema: () => S.fromEffect(provideSchema({ accessToken, spaceId, environmentId, options, schemaOverrides })),
fetchData: ({ schemaDef }) =>
pipe(
S.fromEffect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
unknownToRelativePosixFilePath,
} from '@contentlayer/utils'
import type { HasClock, HasConsole, OT } from '@contentlayer/utils/effect'
import { pipe, provideTestConsole, T, These } from '@contentlayer/utils/effect'
import { O, pipe, provideTestConsole, S, T, These } from '@contentlayer/utils/effect'
import { NodeFsLive } from '@contentlayer/utils/node'

import type { HasDocumentTypeMapState } from '../../fetchData/DocumentTypeMap.js'
Expand All @@ -33,7 +33,7 @@ export const runTest = async ({
const esbuildHash = 'not-important-for-this-test'

const source = yield* $(T.tryPromise(() => makeSource({ contentDirPath, documentTypes })(undefined)))
const coreSchemaDef = yield* $(source.provideSchema(esbuildHash))
const coreSchemaDef = yield* $(pipe(source.provideSchema(esbuildHash), S.runHead, T.map(O.getUnsafe)))

const documentTypeDefs = (Array.isArray(documentTypes) ? documentTypes : Object.values(documentTypes)).map((_) =>
_.def(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { renderTypes } from '@contentlayer/core'
import { provideJaegerTracing } from '@contentlayer/utils'
import { pipe, provideConsole, T } from '@contentlayer/utils/effect'
import { O, pipe, provideConsole, S, T } from '@contentlayer/utils/effect'
import { expect, test } from 'vitest'

import type { DocumentTypes } from '../../index.js'
Expand All @@ -11,7 +11,7 @@ const renderTypeSource = async (documentTypes: DocumentTypes) => {
const esbuildHash = 'not-important-for-this-test'
const schemaDef = await pipe(
T.tryPromise(() => makeSource({ documentTypes, contentDirPath: '' })(undefined)),
T.chain((source) => source.provideSchema(esbuildHash)),
T.chain((source) => pipe(source.provideSchema(esbuildHash), S.runHead, T.map(O.getUnsafe))),
provideJaegerTracing('contentlayer-cli'),
provideConsole,
T.runPromise,
Expand Down
8 changes: 5 additions & 3 deletions packages/@contentlayer/source-files/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,11 @@ export const makeSource: core.MakeSourcePlugin<Args> = (args) => async (sourceKe
extensions: extensions ?? {},
options,
provideSchema: (esbuildHash) =>
pipe(
makeCoreSchema({ documentTypeDefs, options, esbuildHash }),
T.mapError((error) => new SourceProvideSchemaError({ error })),
S.fromEffect(
pipe(
makeCoreSchema({ documentTypeDefs, options, esbuildHash }),
T.mapError((error) => new SourceProvideSchemaError({ error })),
),
),
fetchData: ({ schemaDef, verbose, skipCachePersistence }) =>
pipe(
Expand Down
2 changes: 1 addition & 1 deletion packages/@contentlayer/source-notion/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "contentlayer-source-notion",
"version": "0.0.1-alpha.23",
"version": "0.0.1-alpha.24",
"type": "module",
"exports": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
13 changes: 9 additions & 4 deletions packages/@contentlayer/source-notion/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as core from '@contentlayer/core'
import { processArgs } from '@contentlayer/core'
import { pipe, S, T } from '@contentlayer/utils/effect'
import { pipe, S, SC, T } from '@contentlayer/utils/effect'
import { NotionRenderer } from '@notion-render/client'
import * as notion from '@notionhq/client'

Expand Down Expand Up @@ -41,9 +41,14 @@ export const makeSource: core.MakeSourcePlugin<PluginOptions & core.PartialArgs>
options,
provideSchema: () =>
pipe(
provideSchema({ databaseTypeDefs, options }),
T.provideService(NotionClient)(client),
T.provideService(NotionRendererTag)(renderer),
S.fromEffect(
pipe(
provideSchema({ databaseTypeDefs, options }),
T.provideService(NotionClient)(client),
T.provideService(NotionRendererTag)(renderer),
),
),
S.repeatSchedule(SC.spaced(5_000)),
),
fetchData: ({ schemaDef }) =>
pipe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type ProvideSchemaArgs = {
export const provideSchema = ({ databaseTypeDefs, options }: ProvideSchemaArgs) =>
pipe(
T.gen(function* ($) {
console.log('Providing schema')
return {
documentTypeDefMap: yield* $(provideDocumentTypeDefMap({ databaseTypeDefs, options })),
nestedTypeDefMap: yield* $(provideNestedTypeDefMap()),
Expand All @@ -29,7 +30,10 @@ export const provideSchema = ({ databaseTypeDefs, options }: ProvideSchemaArgs)
hash,
}),
),
T.tap((schemaDef) => T.succeed(core.validateSchema(schemaDef))),
T.tap((schemaDef) => {
console.log(schemaDef.hash)
return T.succeed(core.validateSchema(schemaDef))
}),
),
),

Expand Down
3 changes: 3 additions & 0 deletions packages/@contentlayer/source-notion/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export type PluginOptions = {
client?: ConstructorParameters<typeof notion.Client>[0] | notion.Client
renderer?: ConstructorParameters<typeof NotionRenderer>[0] | NotionRenderer
databaseTypes: DatabaseTypes
dev?: {
polling: false | number
}
}

export type FieldDef = core.FieldDef & { propertyKey?: string }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { provideJaegerTracing } from '@contentlayer/utils'
import { pipe, provideConsole, T } from '@contentlayer/utils/effect'
import { O, pipe, provideConsole, S, T } from '@contentlayer/utils/effect'
import type { DocumentType } from 'contentlayer/source-files'
import { makeSource } from 'contentlayer/source-files'

Expand All @@ -14,7 +14,7 @@ const esbuildHash = 'not-important-for-this-test'
const makeSchema = (documentTypes: Record<string, DocumentType<any>>) =>
pipe(
T.tryPromise(() => makeSource({ documentTypes, contentDirPath: '' })(undefined)),
T.chain((source) => source.provideSchema(esbuildHash)),
T.chain((source) => pipe(source.provideSchema(esbuildHash), S.runHead, T.map(O.getUnsafe))),
provideJaegerTracing('contentlayer-cli'),
provideConsole,
T.runPromise,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import type { HasCwd } from '@contentlayer/core'
import { getConfig, provideCwd } from '@contentlayer/core'
import type { fs } from '@contentlayer/utils'
import { provideJaegerTracing, recRemoveUndefinedValues } from '@contentlayer/utils'
import type { HasConsole } from '@contentlayer/utils/effect'
import { OT, pipe, pretty, provideConsole, T } from '@contentlayer/utils/effect'
import type { HasClock, HasConsole } from '@contentlayer/utils/effect'
import { O, OT, pipe, pretty, provideConsole, S, T } from '@contentlayer/utils/effect'
import { NodeFsLive } from '@contentlayer/utils/node'
import { Command, Option } from 'clipanion'
import * as t from 'typanion'
Expand Down Expand Up @@ -53,11 +53,14 @@ export class DefaultCommand extends Command {
}
}

executeSafe = (): T.Effect<OT.HasTracer & HasCwd & HasConsole & fs.HasFs, unknown, void> =>
executeSafe = (): T.Effect<OT.HasTracer & HasCwd & HasConsole & HasClock & fs.HasFs, unknown, void> =>
pipe(
getConfig({ configPath: this.configPath }),
T.chain((config) =>
T.struct({ source: T.succeed(config.source), schema: config.source.provideSchema(config.esbuildHash) }),
T.struct({
source: T.succeed(config.source),
schema: pipe(config.source.provideSchema(config.esbuildHash), S.runHead, T.map(O.getUnsafe)),
}),
),
T.chain(({ schema, source }) =>
T.tryCatchPromise(
Expand Down