Skip to content
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

Sync/combine types with blueprints #130

Open
silveltman opened this issue Jan 7, 2023 · 6 comments
Open

Sync/combine types with blueprints #130

silveltman opened this issue Jan 7, 2023 · 6 comments

Comments

@silveltman
Copy link

Just starting out with typescript in my projects, to create interfaces for my UI components.

I see a lot af similarities between the typescript interface and the bookshop blueprint.
What would be a good when using both of those in a project?

Like I said, just starting out with typescript, so not sure if this question even makes sense 😅

I'm using Asrto with Svelte components btw. Did take a look at the astro-sendit template, but my understanding of react is very limited.

@silveltman
Copy link
Author

silveltman commented Jan 7, 2023

would a folder structure like this work?

src
|--
  |--components
      |--car
        |-- car.types.ts
        |-- car.svelte
        |-- car.bookshop.yaml

Alternatively, maybe this:

component-library
|--
  |--components
      |--car
        |-- car.types.ts
        |-- car.bookshop.yaml
src
|--
  |--components
      |--car
        |-- car.svelte

@bglw
Copy link
Contributor

bglw commented Feb 2, 2023

Hmm it's a good discussion — I don't know of (m)any existing sites with both Typescript definitions and Bookshop blueprints. I think this is an area we'll start to see more action in soon, so I'll probably be waiting to see what crops up. If you land on anything compelling let me know!

As an aside, we're working on first party Astro Bookshop support which might help build these sites out. Not yet sure how that will interact with typed components though. Will keep you posted!

@silveltman
Copy link
Author

Will do! 👌

Any indication on a release for the first party Astro Bookshop support? Very excited for that 😬😬

@bglw
Copy link
Contributor

bglw commented Mar 23, 2023

No indication yet! Looking at reviewing progress on that soon, so hopefully I'll be back with an update in the near future 🤞

@silveltman
Copy link
Author

Recently started working extensively with Bookshop again, with first party Astro.

I like how bookshop structures enforce the right schema when things come from cloudcannon. However, when working locally it's easy to make type mistakes, for which I won't get any errors.

I also like Astro's schema's using zod. These bring full markdown/yaml typescript editor support and error handling.

At the moment, for schema's, i create them using both the Astro and Cloucannon approach:

// cloudcannon schema
---
title:
description:
image:
  src:
  alt:

seo:
  title:
  description:
  image:
    src:
    alt:
---

// astro schema
import { z } from 'astro:content'
import { description, image, seo, title } from '..'

export const brandsSchema = z.object({
  title,
  description,
  image,
  seo,
})

It's OK, but it could be simplified since they're basically identical. I think one could be generated from the other. I think zod >> markdown makes more sense, since it's typescript therefore easier to read AND is has more options.

The same could be done for bookshop components aswell.

@silveltman
Copy link
Author

Fixed it for collection schema's using ts-to-zod, zod-fixtures adn js-yaml.

I start with a ts interface > generate zod scehama > generate markdown schema.

zod-fixtures allows for default values, which seems like a good usecase for bookshop component blueprints/previews

import { exec } from 'child_process'
import fs from 'fs'
import yaml from 'js-yaml'
import { promisify } from 'util'
import { ZodAny, ZodNumber, ZodString } from 'zod'
import { Fixture, Generator } from 'zod-fixture'

const execAsync = promisify(exec)

async function generateSchemas(collection) {
  if (!collection) return
  try {
    // Run the 'ts-to-zod' command synchronously

    await execAsync(
      `yarn ts-to-zod ./schemas/collections/${collection}/${collection}Schema.d.ts ./schemas/collections/${collection}/${collection}Schema.ts`
    ).then(() => console.log('Successfully generated Zod schema'))

    // Import the generated Zod schema
    const zodSchema = await import(
      `./collections/${collection}/${collection}Schema.ts`
    )

    const schema = zodSchema[collection + 'Schema']

    // Custom generator for nullable strings
    const stringGenerator = Generator({
      schema: ZodString,
      output: () => null,
    })

    // Custom generator for any
    const anyGenerator = Generator({
      schema: ZodAny,
      output: () => null,
    })

    // Custom generator for any
    const numberGenerator = Generator({
      schema: ZodNumber,
      output: () => null,
    })

    // Create a fixture with the custom generator
    const fixture = new Fixture({
      seed: 1,
      array: {
        min: 1,
        max: 1,
      },
    }).extend([stringGenerator, anyGenerator, numberGenerator])
    const fixtureSchema = fixture.fromSchema(schema)

    // Convert to YAML
    const yamlFixture = yaml.dump(fixtureSchema)

    // Write to Markdown file
    fs.writeFileSync(
      `./schemas/collections/${collection}/${collection}Schema.md`,
      `---\n${yamlFixture}---`
    )
    console.log('Successfully generated markdown schema')
  } catch (error) {
    console.error('Error in schema generation and conversion:', error)
  }
}

const collections = [
  'brands',
  'categories',
  'employees',
  'pages',
  'policies',
  'posts',
  'products',
  'reviews',
  'services',
]

collections.forEach((collection) => generateSchemas(collection))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants