saberland/saber

Do you want to work on this issue?

You can request for a bounty in order to promote it!

Saber Functions #183

egoist posted onGitHub

<!-- Please ask questions via following several ways. -->

<!-- https://chat.saber.land/ -->

<!-- https://stackoverflow.com/questions/ask?tags=saberjs -->

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)
}

<small>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.</small>

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)

Maybe "Functional Routes" or "Manual Routes"?

posted by krmax44 almost 6 years ago

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

posted by egoist almost 6 years ago

@issuehunt has funded $150.00 to this issue.


posted by issuehunt-app[bot] almost 6 years ago

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.

posted by galvez almost 6 years ago

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

posted by krmax44 over 5 years ago

Just updated the proposal ⬆️

posted by egoist almost 5 years ago

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

posted by krmax44 almost 4 years ago

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.

posted by TYKUHN2 over 2 years ago

Fund this Issue

$150.00
Funded
Only logged in users can fund an issue

Pull requests

Recent activities

issuehunt funded 150.00 for saberland/saber# 183
almost 6 years ago