stapigen
v1.4.1
Published
Generate static APIs for any set of files
Downloads
6
Maintainers
Readme
Table of Contents
About
Stapigen allows you to generate a static, file-based JSON API out of an existing set of files. You can, for example, use it to generate an API for yaml or markdown files, like a JAMstack blog.
You can easily provide your own file parser, which allows you to generate an API for any filetype.
It's completely static, so you can host it with any static webserver or even Github Pages.
Quickstart
- Generate an example config file:
npx stapigen init
Change configuration file as needed (see Configuration)
Build api:
npx stapigen build
Commands
Run npx stapigen help [command]
for detailed and up-to-date documentation.
init
:
Usage: stapigen init [options]
generates an example config file
Options:
-f, --file-name <filename> config file name (default: "stapigen.conf.js")
-h, --help display help for command
build
:
Usage: stapigen build [options]
builds a json api from input files
Options:
-c, --config-file <file-path> path to config file (default: "stapigen.conf.js")
-h, --help display help for command
Stapigen will build .json
files using a parser for every entpoint (see output.schema)
Output JSON Structure
index.json
: array containing all resources for a pathID.json
: file containing data for a specific resource
The id is the same as the filename, but always in lowercase.
Generated json for a single resource has following structure:
{
"id": "RESOURCE_ID",
"tags": { "TAGNAME": "TAG_VALUE", "TAGNAME2": "TAG_VALUE2" },
"data": { "PARSED_PROPERTY": "VALUE", "PARSED_PROPERTY2": "VALUE" }
}
index.json
contains an array:
[
{
"id": "RESOURCE_ID1",
"tags": { "TAGNAME": "TAG_VALUE", "TAGNAME2": "TAG_VALUE2" },
"data": { "PARSED_PROPERTY": "VALUE", "PARSED_PROPERTY2": "VALUE" }
}
]
Configuration
Stapigen is configured through a configuration file. It looks for stapigen.conf.js
by default.
This can be changed through the --config
flag.
(see npx stapigen help build
)
The configuration is a file exporting a javascript object as NodeJS module.
example:
module.exports = {
input: {
dir: 'input',
include: '**/*.txt',
schema: 'year/month/day',
},
output: {
dir: 'output',
schema: 'category/year',
},
parser: [
{
extensions: ['.txt'],
parse: ({ name, content }) => ({ filename: name, content }),
},
],
plugins: [],
};
input
Defines how the source files are structured.
input.dir
Location of input files.
input.include
(optional)
Glob pattern for files to include. Everything not matching this pattern will be ignored.
examples:
- only include specific files:
**/*.txt
- only include files in a specific directory:
+(a|b)/**/*
Matching is done using minimatch.
input.schema
(optional)
Structure of input files. e.g. year/month/day
Stapigen generates tags out of the input directories (e.g. year, month, day
). These are written in to the output json files and are used to generate output collections. (see output.schema)
If omitted or empty (''
), it just parses everything recursively in input.dir
, ignoring the file structure.
output
Defines how the api should be structured.
output.dir
Location of output files.
output.schema
(optional)
Defines the folder structure for the generated json files. e.g. category/year
Stapigen generates collections for each folder name based on input folders (tags, see input.schema). If it can't find a input folder with the same name, it filters the json data by properties with the output foldername.
For example:
When defining:
input.schema: "year/month/day"
and
output.schema: "category/year"
Stapigen will filter all input files by the property category
and by the tag year (tag = input folder name).
With this example, the file input/2020/12/13/myfile.md
with following content:
---
category: magic
---
# my file
will result in a file output/magic/2020/myfile.json
. (when providing a parser for .md
files)
If omitted or empty (''
), is just generates files directly in output.dir
without creating folders.
parser
Array containing parsers for input files.
Stapigen does currently not include a parser, so you have to write your own!
A parser is a object with following properties:
extensions
: array containing supported file extensions, e.g.['.md', '.txt']
parse
: a parse function receiving a file object{name, content}
and returning an object with the parsed data.
Typescript typedefinitions:
type GenericObjectData = {
[key: string]: unknown;
};
type Parser = {
extensions: string[];
parse: ParserFunction;
};
type ParserFunction = (file: {
name: string;
content: string;
}) => GenericObjectData;
For example, this configuration:
// [...]
parser: [
{
extensions: ['.txt'],
parse: ({ name, content }) => ({ filename: name, content }),
},
],
// [...]
will generate .json
files from .txt
files with following content:
{
// [...] (metadata)
"data": {
"filename": "FILE_NAME",
"content": "FILE_CONTENT_AS_STRING"
}
}
plugins
Array containing plugins, you might want to use.
stapigen allows you to add plugins, powered by krog
const myPlugin = require('./myPlugin');
//...
plugins: [
myPlugin,
],
//...
For plugin authors: A plugin is just an object with the following properties:
name
: the name of the pluginhooks
: an object with hooks (e.g.{ 'before:write_collections' : () => {} }
)
A plugin can hook into specific hook points. The following hooks are available:
hooks
before:write_collections
Called before writing json files, receives the parsed collections as argument. You can also modify the collections or add new ones by returning a new array.
For example:
const plugin = {
name: 'collections-logger',
hooks: {
'before:write_collections': ({ collections }) => {
console.log('before:write_collections');
console.log(collections);
// modify collections by returning a new arguments object
return {
collections: [
...collections,
{
id: 'my-new-collection',
tags: {
myTag: 'my-tag-value',
},
data: {
myProperty: 'my-property-value',
},
},
],
};
},
},
};
Development
Run tests
yarn run test
Author
👤 Timo Bechtel
- Twitter: @TimoBechtel
- GitHub: @TimoBechtel
- Website: https://timobechtel.com
🤝 Contributing
Contributions, issues and feature requests are welcome!
- Check issues
- Fork the Project
- Create your Feature Branch (
git checkout -b feat/AmazingFeature
) - Test your changes
yarn run test
- Commit your Changes (
git commit -m 'feat: add amazingFeature'
) - Push to the Branch (
git push origin feat/AmazingFeature
) - Open a Pull Request
Commit messages
This project uses semantic-release for automated release versions. So commits in this project follow the Conventional Commits guidelines. I recommend using commitizen for automated commit messages.
Show your support
Give a ⭐️ if this project helped you!
This README was generated with ❤️ by readme-md-generator