Skip to content

Commit d83a46e

Browse files
committed
feat(cli): manage recipe index
1 parent 89dd440 commit d83a46e

File tree

5 files changed

+89
-30
lines changed

5 files changed

+89
-30
lines changed

bun.lockb

32 Bytes
Binary file not shown.

packages/cli/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"@effect/platform": "0.69.28",
1616
"effect": "3.10.19",
1717
"fs-extra": "11.2.0",
18+
"globby": "14.0.2",
1819
"pkg-dir": "8.0.0",
1920
"yargs": "17.7.2"
2021
},

packages/cli/src/client.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ const Utils = Schema.Array(
1414
const Recipe = Schema.Struct({
1515
id: Schema.String,
1616
filename: Schema.String,
17-
slotRecipe: Schema.Boolean,
1817
content: Schema.String,
1918
})
2019

@@ -47,6 +46,7 @@ export const fetchComponentById = (id: string, config: Config) =>
4746
),
4847
HttpClient.get(`${API_URL}/recipes/${id}.json`).pipe(
4948
Effect.flatMap(HttpClientResponse.schemaBodyJson(Recipe)),
49+
Effect.catchAll(() => Effect.succeed(null)),
5050
Effect.scoped,
5151
Effect.provide(FetchHttpClient.layer),
5252
),

packages/cli/src/index.ts

+35-29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import yargs from 'yargs'
88
import { hideBin } from 'yargs/helpers'
99
import { fetchComponents, fetchUtils } from './client'
1010
import { getConfig } from './get-config'
11+
import { updateRecipeIndex } from './recipes'
1112

1213
const isEmpty = (arr: string[]) => arr.length === 0
1314

@@ -45,44 +46,49 @@ const main = async () => {
4546
getConfig(),
4647
Effect.tap(() => spinner.start('Installing components...')),
4748
Effect.flatMap((config) =>
48-
Effect.all([
49-
pipe(
50-
fetchComponents(config, argv),
51-
Effect.flatMap((components) =>
52-
Effect.forEach(components, ({ component: { variants }, recipe }) =>
53-
Effect.all([
54-
Effect.forEach(variants, (variant) =>
55-
Effect.promise(() =>
56-
fs.outputFile(
57-
path.join(config.paths.components, variant.file),
58-
variant.content,
49+
pipe(
50+
Effect.all([
51+
pipe(
52+
fetchComponents(config, argv),
53+
Effect.flatMap((components) =>
54+
Effect.forEach(components, ({ component: { variants }, recipe }) =>
55+
Effect.all([
56+
Effect.forEach(variants, (variant) =>
57+
Effect.promise(() =>
58+
fs.outputFile(
59+
path.join(config.paths.components, variant.file),
60+
variant.content,
61+
),
5962
),
6063
),
61-
),
64+
recipe
65+
? Effect.promise(() =>
66+
fs.outputFile(
67+
path.join(config.paths.recipes, recipe.filename),
68+
recipe.content,
69+
),
70+
)
71+
: Effect.succeed(null),
72+
]),
73+
),
74+
),
75+
),
76+
pipe(
77+
fetchUtils(config),
78+
Effect.flatMap((helpers) =>
79+
Effect.forEach(helpers, (helper) =>
6280
Effect.promise(() =>
6381
fs.outputFile(
64-
path.join(config.paths.recipes, recipe.filename),
65-
recipe.content,
82+
path.join(config.paths.components, helper.filename),
83+
helper.content,
6684
),
6785
),
68-
]),
69-
),
70-
),
71-
),
72-
pipe(
73-
fetchUtils(config),
74-
Effect.flatMap((helpers) =>
75-
Effect.forEach(helpers, (helper) =>
76-
Effect.promise(() =>
77-
fs.outputFile(
78-
path.join(config.paths.components, helper.filename),
79-
helper.content,
80-
),
8186
),
8287
),
8388
),
84-
),
85-
]),
89+
]),
90+
Effect.flatMap(() => updateRecipeIndex(config)),
91+
),
8692
),
8793

8894
Effect.catchAll((error) => Effect.fail(error.message)),

packages/cli/src/recipes.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import fs from 'node:fs/promises'
2+
import { parse } from 'node:path'
3+
import { Effect, pipe } from 'effect'
4+
import { globby } from 'globby'
5+
import type { Config } from './get-config'
6+
7+
export const updateRecipeIndex = (config: Config) =>
8+
Effect.promise(() =>
9+
globby([`${config.paths.recipes}/*.ts`, `!${config.paths.recipes}/index.ts`]),
10+
)
11+
.pipe(
12+
Effect.map((recipes) => recipes.sort()),
13+
Effect.flatMap((recipes) =>
14+
pipe(
15+
Effect.forEach(recipes, (recipe) =>
16+
pipe(
17+
Effect.promise(() => fs.readFile(recipe, 'utf-8')),
18+
Effect.map((content) => ({
19+
filename: parse(recipe).name,
20+
exportName: content.match(/export const (\w+)/)?.[1] ?? '',
21+
slotRecipe: content.includes('defineSlotRecipe'),
22+
})),
23+
),
24+
),
25+
),
26+
),
27+
)
28+
.pipe(
29+
Effect.map(
30+
(recipes) =>
31+
`import type { RecipeConfig, RecipeVariantRecord, SlotRecipeConfig } from '@pandacss/dev'
32+
${recipes.map(({ filename, exportName }) => `import { ${exportName} } from './${filename}'`).join('\n')}
33+
34+
export const recipes: Record<string, Partial<RecipeConfig<RecipeVariantRecord>>> = {
35+
${recipes
36+
.filter((recipe) => !recipe.slotRecipe)
37+
.map(({ exportName }) => ` ${exportName},`)
38+
.join('\n')}
39+
}
40+
41+
export const slotRecipes: Record<string, Partial<SlotRecipeConfig>> = {
42+
${recipes
43+
.filter((recipe) => recipe.slotRecipe)
44+
.map(({ exportName }) => ` ${exportName},`)
45+
.join('\n')}
46+
}
47+
`,
48+
),
49+
Effect.flatMap((content) =>
50+
Effect.promise(() => fs.writeFile(`${config.paths.recipes}/index.ts`, `${content}`)),
51+
),
52+
)

0 commit comments

Comments
 (0)