saber icon indicating copy to clipboard operation
saber copied to clipboard

Saber Functions

Open egoist opened this issue 5 years ago • 8 comments

Issuehunt badges

RFC: Saber Functions

functions folder

Functions are used to fetch data that you can inject to pages at build time, let's say you have a posts.js inside functions folder:

exports.handler = async ({ type }) => {
  const posts = await getAllPostsFromApi()
  return posts.filter(post => post.type === type)
}

Since we need to get the return value before running webpack, you can only write JavaScript with features supported by your system's Node version.

Then a function called posts will be available and you can use it like this in a page:

<script>
export const config = {
  injectProps: {
    drafts: {
      function: 'posts',
      options: {
        type: 'draft'
      }
    }
  }
}

export default {
  props: ['drafts']
}
</script>

By using injectProps here Saber will call the function at build time and inline result in your JavaScript bundle.

Pagination

We can create pagination based on injected props:

<script>
export const config = {
  paginate: {
    prop: 'drafts',
    perPage: 30
  },

  injectProps: {
    drafts: {
      function: 'posts',
      options: {
        type: 'draft'
      }
    }
  }
}

export default {
  props: ['drafts']
}
</script>

Exporting function

A function can be exported as a page just like a normal page, only thing you need to do is setting config.export option to true:

// functions/atom.xml.js
const getPosts = require('../get-posts')

exports.handler = async () => {
  const posts = await getPosts({ type: 'public' })
  const xml = generateXMLFeed(posts)
  return xml
}

exports.config = {
  export: true
}

When export is true, Saber automatically infers the actual link from its filename, in this case it would be /atom.xml. You can also set it to a string to use whatever permalink you want, e.g. /subscribe/rss.xml.

When export is true, the function's argument would be undefined unless you use dynamic parameter in its filename, for example functions/pages/[slug].json.js:

exports.handler = ({ slug }) => {
  return getPageBySlug(slug)
}

exports.config = {
  export: true
}

exports.getStaticPaths = () => {
  return [
    { slug: 'hello-world' },
    { slug: 'another-page' }
  ]
}

Because the path is dynamic you also need getStaticPaths to define a list of paths that need to be rendered at build time.

Now when you visit /pages/hello-world.json, then function argument will be { slug: 'hello-world' }

Adding a function from plugins

saber.functions.add(FunctionObject)

IssueHunt Summary

Backers (Total: $150.00)

Become a backer now!

Or submit a pull request to get the deposits!

Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

egoist avatar May 14 '19 10:05 egoist

Maybe "Functional Routes" or "Manual Routes"?

krmax44 avatar May 14 '19 13:05 krmax44

#72 won't be needed if we have this feature instead.

egoist avatar May 19 '19 12:05 egoist

@issuehunt has funded $150.00 to this issue.


issuehunt-oss[bot] avatar Jun 25 '19 07:06 issuehunt-oss[bot]

In NuxtPress (currently in development), I did a generic abstraction of this.

Every source is identified by a full path. For every source, the engine automatically does a GET request to /api/source/{uri}.

If you don't provide your own API handlers, it will perform static fetch() to the distribution.

A source is a JSON with { body, type }. Different types can be used to trigger different rendering components.

So in generate mode, if you have a route something/foobar.md, source type will be md and it will go through the Markdown loader.

A /static/sources/something/foobar.json will also be made available for the static JSON GET.

Then agan, if you do provide your own API handlers, data can come from anywhere you like.

galvez avatar Jun 25 '19 13:06 galvez

I also quite like the implementation that Sapper uses: https://sapper.svelte.dev/docs#Server_routes

krmax44 avatar Sep 07 '19 14:09 krmax44

Just updated the proposal ⬆️

egoist avatar Apr 15 '20 18:04 egoist

I'm currently building something similar: rollup-plugin-computed

krmax44 avatar Apr 27 '21 12:04 krmax44

Is this project still being worked on? The website seems parked by adware/viruses. If it is, I can take a look at this issue.

TYKUHN2 avatar Aug 06 '22 21:08 TYKUHN2