Skip to content

Releases: FlatbreadLabs/flatbread

🥬 Romaine, Resolvers, Relations, Renovations!

05 Aug 02:24
Compare
Choose a tag to compare

First off, I'd like to extend a warm welcome to our new contributors @odama626 and @Sheharyar566!

This is a mighty large release, JAMpacked with juicy new features and fixes.

🏡 Organization updates

  • We created a dedicated @FlatbreadLabs organization which Flatbread now belongs to
  • @odama626 is now a co-maintainer of Flatbread & a member of the core team 🙌
  • We're working on an official Flatbread docs & marketing site to help others get this bread
  • Add badges & Slack link to docs #23
    • Dear prospective contributors, we'd love to have ya on the project - join the Slack to get started!

Features

  • Bounded GraphQL server cache #22

  • Recursive directory scan for source-filesystem #25

    • Glob matches are supported for content paths to import from nested directories.
      {
        path: 'content/markdown/posts/**/*.md',
        collection: 'PostCategoryBlob',
        refs: {
          authors: 'Author',
        },
      },
      
    • Named globs will derive meaningful data from a directory name it matches. These are made available as a field on that collection within the GraphQL API:
      {
        path: 'content/markdown/posts/[category]/[slug].md',
        collection: 'PostCategory',
        refs: {
          authors: 'Author',
        },
      },
  • Allow field overrides #29

  • Allow multiple transformers #30

    • You can now provide an array of transformers to match collections with mixed file types
      export default defineConfig({
        transformer: [transformerMarkdown(transformerConfig), transformerYaml()],
        ...
      }
  • Allow serverside function flatbread #31

    • Exposes a direct way to resolve GraphQL queries passed to a query function baked with Flatbread schema.
      import { FlatbreadProvider } from "@flatbread/core";
      
      // Run Flatbread as a function to execute a subquery
      const flatbread = new FlatbreadProvider({
        // a Flatbread config object here...
      });
      
      const gqlQuery = `
        query Foo {
          allPosts {
            id
            title
          }
        }
      `;
      
      const { data } = await flatbread.query({
        source: gqlQuery,
      });
  • Introduce concept of custom resolver plugins:

    • @flatbread/resolver-svimg #32
      • Optimizes images in your data to next-gen formats using src-sets and placeholders
      import { createSvImgField } from '@flatbread/resolver-svimg';
      
      export default defineConfig({
      ...
      content: [
        {
          path: 'content/markdown/authors',
          collection: 'Author',
          refs: {
            friend: 'Author',
          },
          overrides: [
            createSvImgField('image', {
              inputDir: 'static/authorImages',
              outputDir: 'static/g',
              srcGenerator: (path) => '/g/' + path,
            }),
          ],
        },
       ],
      });
  • Support alternative config file extensions #51

    • You should now be able to run Flatbread in any framework and environment, regardless of scope (CJS/ESM).
    • Supports the following config flavors:
      • flatbread.config.js
      • flatbread.config.mjs
      • flatbread.config.cjs
      • flatbread.config.ts
      • flatbread.config.mts
      • flatbread.config.cts

Fixes

  • Relational/post-resolved filtering via GraphQL subquery #35
  • Set up RenovateBot & pin dependencies #44 #46
  • Build Flatbread on Windows #85
  • Run CI on external PRs #68

⚠️ Breaking changes!

  • import { filesystem } from ‘flatbread’ is now import { sourceFilesystem } from ‘flatbread’
  • import { markdownTransformer } from ‘flatbread’ is now import { transformerMarkdown } from ‘flatbread’

Simplified setup

30 Jun 05:20
Compare
Choose a tag to compare
Simplified setup Pre-release
Pre-release

Introduces improvements to package interdependency ranges.

Previously, a version bump on a package could immediately outdate usage of previous versions of that package in tandem with a peer dependency. Now there are explicit ranges declared which can better follow semvar.

Cleans up the common, default use-case of Flatbread

Now you can import the Markdown Transformer and Source Filesystem from flatbread directly, instead of installing the plugins as separate. This is still cross-compatible with importing directly from the plugins themselves.

The example below highlights an example config of the typical markdown file flow:

import { defineConfig, markdownTransformer, filesystem } from 'flatbread';

const transformerConfig = {
  markdown: {
    gfm: true,
    externalLinks: true,
  },
};
export default defineConfig({
  source: filesystem(),
  transformer: markdownTransformer(transformerConfig),

  content: [
    {
      path: 'content/posts',
      collection: 'Post',
      refs: {
        authors: 'Author',
      },
    },
    {
      path: 'content/authors',
      collection: 'Author',
      refs: {
        friend: 'Author',
      },
    },
  ],
});

Node 16

From this point on, I'm only focused on supporting Node LTS which is v16+

Docs

Updated examples, fixed some links, and updated scripts 🫠

Changes to build-in fields

25 Jun 23:07
Compare
Choose a tag to compare
Pre-release

The bread's alive! Having a fun time champagne-testing this in Puerh.wtf's rewrite into SvelteKit x Flatbread 🥳

Feeling incredibly pleased with how freeing & robust Flatbread makes the experience of building a static site fueled by a relational, flat-file data source. I'm enjoying it much more than my experiences with doing the same in Gridsome and Gatsby, so hopefully that means we're onto something!

Now onto the juicy deets...

New features

  • We're now releasing under the normal latest tag, so all packages can be installed following the pattern of pnpm i -D <package_name> without specifying a version.
  • A new built-in field is made available called _collection. This field resolves to the collection name the returned elements belong to, which may not seem useful at the surface but can be powerful for advanced workflows where multiple collections are merged after querying, for example when building a file tree component.

⚠️ Breaking changes!

  • typeName has been renamed to collection in flatbread.config.js for the source-filesystem plugin
    • Example of a valid Flatbread config file with this change:
    import defineConfig from '@flatbread/config';
    import transformer from '@flatbread/transformer-markdown';
    import filesystem from '@flatbread/source-filesystem';
    
    const transformerConfig = {
    markdown: {
      gfm: true,
      externalLinks: true,
    },
    };
    export default defineConfig({
    source: filesystem(),
    transformer: transformer(transformerConfig),
    
    content: [
      {
        path: 'content/markdown/posts',
        collection: 'Post', // this field used to be called `typeName`
        refs: {
          authors: 'Author',
        },
      },
      {
        path: 'content/markdown/authors',
        collection: 'Author',
        refs: {
          friend: 'Author',
        },
      },
    ],
    });
  • Fields created by Flatbread have been prefixed with an underscore:
    • slug -> _slug
    • filename -> _filename
    • path -> _path
    • content -> _content

The Alpha bread

25 Nov 03:07
Compare
Choose a tag to compare
The Alpha bread Pre-release
Pre-release

Well here we are. The damn thing kinda really actually works 👁‍🗨. You can do the core schtick of having markdown files in your repo get automatically converted to a schema consisting of GraphQL typedefs + resolvers that retrieve that data.

That gives a real swell experience. The end user doesn't have to give two shits about what's going on behind the scenes. They can just declare where their data is, the typeName of it, wait a moment while magic little ferrets and goats rummage around in the console as their server starts alongside their pretty web app, then query the data in those flat file suckers by their id (obviously way more queries will be added for each content type, but this is the proof of worth moment I've been waiting on for a grand total of 17 short days, so I would say very cool and awesome and dope and sick, in fact) and it shows up on your screen!

image

Oh I also completely ripped out the GraphQL server in the CLI and slapped in Apollo Server (as pictured above). The CLI itself saw a bunch of tweaks and now the GraphQL server stands alone and does its own Flatbread thing, encapsulating the functions from the core and config packages. The CLI is kinda just a pretty scheduler and watcher over the Flatbread/GraphQL server process and your other script.

Bonus point, you can totally roll your own GraphQL server while making use of Flatbread without even touching the flatbread package. You literally only need these two functions to plug the resultant GraphQL schema into whatever you want:

import {loadConfig} from '@flatbread/config';
import generateSchema from '@flatbread/core';

const config = await loadConfig();
const schema = await generateSchema(config);

...

Take a look at flatbread/src/graphql/server.ts for an example on how to roll your own GQL server & editor.

It doesn't all work yet but it's gettin' there!

21 Nov 13:32
Compare
Choose a tag to compare

The CLI, user config module, filesystem source plugin, and markdown transformer all work!

The playground shows a proof of concept in its package.json where you can boot up Flatbread alongside a dev or build process.

Neat CLI stuff

You can pass Flatbread a peer script to run alongside it by separating the two scripts (and their options) with --:

"scripts": {
  "dev": "flatbread start -o -- svelte-kit dev",
  "flatbread:help": "flatbread start -h",
  "build": "flatbread start -- svelte-kit build",
}

Flatbread captures that second script's options/arguments, automatically detects and uses the package manager you're using (as long as it's pnpm, yarn, or npm), and delays the start of that peer process until Flatbread finishes launching its GraphQL server. This approach cleanly avoids race conditions where your dev server might crank open before Flatbread has had time to parse your content into a schema, etc.

This strategy also allows a nice interface for you to query inside your statically generated apps. You'll get a predictable GraphQL server on a separate process & port from your dev/build process. Flatbread doesn't give a shit what framework you're using. If you can server-side query that endpoint (i.e. http://localhost:5057/graphql) from within your app ( i.e. http://localhost:3000), you're off to the races.

No more global vendor lock-in à la Gatsby/Gridsome; bring the tools you want to use.

New Contributors

Full Changelog: https://github.com/tonyketcham/flatbread/commits/v0.0.2