Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sourcebit

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sourcebit - npm Package Compare versions

Comparing version 0.8.1 to 0.9.0

55

bin/sourcebit.js
#!/usr/bin/env node
const commander = require("commander");
const sourcebit = require("../index");
const path = require("path");
const pkg = require("../package.json");
const commander = require('commander');
const sourcebit = require('../index');
const path = require('path');
const pkg = require('../package.json');
commander
.version(pkg.version)
.command("fetch")
.option("-c, --configPath", "specify the location of the configuration file")
.option(
"-C, --cache",
"force Sourcebit to use a filesystem cache, even when `watch` is disabled"
)
.option("-w, --watch", "run continuously in watch mode")
.option("-q, --quiet", "disable logging messages to the console")
.action(({ cache, configPath: customConfigPath, quiet, watch }) => {
const configPath = path.resolve(
process.cwd(),
customConfigPath || "sourcebit.js"
);
const config = require(configPath);
const runtimeParameters = {
cache,
quiet,
watch
};
.version(pkg.version)
.command('fetch')
.option('-c, --configPath', 'specify the location of the configuration file')
.option('-C, --cache', 'force Sourcebit to use a filesystem cache, even when `watch` is disabled')
.option('-w, --watch', 'run continuously in watch mode')
.option('-q, --quiet', 'disable logging messages to the console')
.action(({ cache, configPath: customConfigPath, quiet, watch }) => {
const configPath = path.resolve(process.cwd(), customConfigPath || 'sourcebit.js');
const config = require(configPath);
const runtimeParameters = {
cache,
quiet,
watch
};
sourcebit.fetch(config, runtimeParameters);
});
sourcebit.fetch(config, runtimeParameters);
});
commander.on("command:*", () => {
console.error(
"Invalid command: %s\nSee --help for a list of available commands.",
commander.args.join(" ")
);
commander.on('command:*', () => {
console.error('Invalid command: %s\nSee --help for a list of available commands.', commander.args.join(' '));
process.exit(1);
process.exit(1);
});
commander.parse(process.argv);

@@ -11,14 +11,14 @@ # Contributing guidelines

```
git clone https://github.com/stackbithq/sourcebit.git /Users/foobar/sourcebit
cd /Users/foobar/sourcebit
npm install
```
```
git clone https://github.com/stackbithq/sourcebit.git /Users/foobar/sourcebit
cd /Users/foobar/sourcebit
npm install
```
2. Navigate to a directory where there's a [`sourcebit.js` configuration file](https://github.com/stackbithq/sourcebit#manual-configuration) and run the Sourcebit binary
```
cd /Users/foobar/my-project
node /Users/foobar/sourcebit/bin/sourcebit.js fetch
```
```
cd /Users/foobar/my-project
node /Users/foobar/sourcebit/bin/sourcebit.js fetch
```

@@ -25,0 +25,0 @@ ## Creating a plugin

@@ -1,30 +0,26 @@

require("dotenv").config();
const Sourcebit = require("./lib/sourcebit");
require('dotenv').config();
const Sourcebit = require('./lib/sourcebit');
module.exports.fetch = (config, runtimeParameters, transformCallback) => {
if (!config) {
throw new Error(
"ERROR: Could not find a valid `sourcebit.js` configuration file."
);
}
if (!config) {
throw new Error('ERROR: Could not find a valid `sourcebit.js` configuration file.');
}
if (typeof runtimeParameters === "function") {
transformCallback = runtimeParameters;
runtimeParameters = {};
}
if (typeof runtimeParameters === 'function') {
transformCallback = runtimeParameters;
runtimeParameters = {};
}
const instance = new Sourcebit({ runtimeParameters, transformCallback });
const { plugins = [] } = config;
const instance = new Sourcebit({ runtimeParameters, transformCallback });
const { plugins = [] } = config;
instance.loadPlugins(plugins);
instance.loadPlugins(plugins);
const transformData = instance
.bootstrapAll()
.then(() => instance.transform());
const transformData = instance.bootstrapAll().then(() => instance.transform());
if (typeof transformCallback !== "function") {
return transformData;
}
if (typeof transformCallback !== 'function') {
return transformData;
}
};
module.exports.Sourcebit = Sourcebit;

@@ -1,33 +0,24 @@

const fs = require("fs");
const util = require("util");
const yaml = require("yaml");
const fs = require('fs');
const util = require('util');
const yaml = require('yaml');
const writeFile = util.promisify(fs.writeFile);
module.exports.writeFrontmatterMarkdown = (
filePath,
{ body = "", frontmatter = {} }
) => {
const lines = [
"---",
yaml.stringify(frontmatter).trim(),
"---",
body ? body.toString().trim() : "",
""
];
const content = lines.join("\n");
module.exports.writeFrontmatterMarkdown = (filePath, { body = '', frontmatter = {} }) => {
const lines = ['---', yaml.stringify(frontmatter).trim(), '---', body ? body.toString().trim() : '', ''];
const content = lines.join('\n');
return writeFile(filePath, content);
return writeFile(filePath, content);
};
module.exports.writeJSON = (filePath, data) => {
const content = JSON.stringify(data, null, 2);
const content = JSON.stringify(data, null, 2);
return writeFile(filePath, content);
return writeFile(filePath, content);
};
module.exports.writeYAML = function(filePath, data) {
const content = yaml.stringify(data);
const content = yaml.stringify(data);
return writeFile(filePath, content);
return writeFile(filePath, content);
};

@@ -1,365 +0,355 @@

const debug = require("debug");
const fs = require("fs");
const mkdirp = require("mkdirp");
const ora = require("ora");
const path = require("path");
const { cloneDeep } = require("lodash");
const {
writeFrontmatterMarkdown,
writeJSON,
writeYAML
} = require("./file-writers");
const debug = require('debug');
const fs = require('fs');
const mkdirp = require('mkdirp');
const ora = require('ora');
const path = require('path');
const { cloneDeep } = require('lodash');
const { writeFrontmatterMarkdown, writeJSON, writeYAML } = require('./file-writers');
const FILE_WRITERS = {
"frontmatter-md": writeFrontmatterMarkdown,
json: writeJSON,
yml: writeYAML
'frontmatter-md': writeFrontmatterMarkdown,
json: writeJSON,
yml: writeYAML
};
class Sourcebit {
constructor({
cacheFile = path.join(process.cwd(), ".sourcebit-cache.json"),
runtimeParameters = {},
transformCallback
} = {}) {
this.cacheFilePath = cacheFile;
this.context = {};
this.fileWriterCache = [];
this.onTransform = transformCallback;
this.pluginBlocks = [];
this.pluginModules = {};
this.runtimeParameters = runtimeParameters;
constructor({ cacheFile = path.join(process.cwd(), '.sourcebit-cache.json'), runtimeParameters = {}, transformCallback } = {}) {
this.cacheFilePath = cacheFile;
this.context = {};
this.fileWriterCache = [];
this.onTransform = transformCallback;
this.pluginBlocks = [];
this.pluginModules = {};
this.runtimeParameters = runtimeParameters;
this.isCacheEnabled = Boolean(
runtimeParameters.cache === undefined
? runtimeParameters.watch
: runtimeParameters.cache
);
}
this.isCacheEnabled = Boolean(runtimeParameters.cache === undefined ? runtimeParameters.watch : runtimeParameters.cache);
}
async bootstrapAll() {
this.isBootstrapping = true;
async bootstrapAll() {
this.isBootstrapping = true;
let queue = Promise.resolve();
let queue = Promise.resolve();
this.context = this.loadContextFromCache() || {};
this.context = this.loadContextFromCache() || {};
this.pluginBlocks.forEach((_, pluginIndex) => {
queue = queue.then(() => this.bootstrapPluginAtIndex(pluginIndex));
});
this.pluginBlocks.forEach((_, pluginIndex) => {
queue = queue.then(() => this.bootstrapPluginAtIndex(pluginIndex));
});
await queue;
await queue;
this.isBootstrapping = false;
this.isBootstrapping = false;
this.saveContextToCache();
}
this.saveContextToCache();
}
async bootstrapPluginAtIndex(index) {
const pluginBlock = this.pluginBlocks[index];
const { options } = pluginBlock;
const plugin = this.pluginModules[index];
const pluginName = this.getNameOfPluginAtIndex(index);
async bootstrapPluginAtIndex(index) {
const pluginBlock = this.pluginBlocks[index];
const { options } = pluginBlock;
const plugin = this.pluginModules[index];
const pluginName = this.getNameOfPluginAtIndex(index);
if (typeof plugin.bootstrap === "function") {
await plugin.bootstrap({
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: this.getContextForNamespace.bind(this, pluginName),
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, options),
refresh: this.transform.bind(this),
setPluginContext: this.setContextForNamespace.bind(this, pluginName)
});
if (typeof plugin.bootstrap === 'function') {
await plugin.bootstrap({
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: this.getContextForNamespace.bind(this, pluginName),
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, options),
refresh: this.transform.bind(this),
setPluginContext: this.setContextForNamespace.bind(this, pluginName)
});
}
pluginBlock._isBootstrapped = true;
}
pluginBlock._isBootstrapped = true;
}
debug(...parameters) {
return this.getDebugMethodForCore().call(this, parameters);
}
debug(...parameters) {
return this.getDebugMethodForCore().call(this, parameters);
}
getContext() {
return cloneDeep(this.context);
}
getContext() {
return cloneDeep(this.context);
}
getContextForNamespace(namespace) {
return this.context[namespace] ? cloneDeep(this.context[namespace]) : {};
}
getContextForNamespace(namespace) {
return this.context[namespace] ? cloneDeep(this.context[namespace]) : {};
}
getDebugMethodForCore() {
return debug('core');
}
getDebugMethodForCore() {
return debug("core");
}
getDebugMethodForPlugin(pluginName) {
return debug(`plugin:${pluginName}`);
}
getDebugMethodForPlugin(pluginName) {
return debug(`plugin:${pluginName}`);
}
getNameOfPluginAtIndex(index) {
return this.pluginModules[index].name || `plugin-${index}`;
}
getNameOfPluginAtIndex(index) {
return this.pluginModules[index].name || `plugin-${index}`;
}
loadContextFromCache() {
if (!this.isCacheEnabled) return;
loadContextFromCache() {
if (!this.isCacheEnabled) return;
try {
const data = fs.readFileSync(this.cacheFilePath, 'utf8');
try {
const data = fs.readFileSync(this.cacheFilePath, "utf8");
return JSON.parse(data);
} catch (error) {
this.debug(error);
}
}
return JSON.parse(data);
} catch (error) {
this.debug(error);
loadPlugins(plugins) {
this.pluginBlocks = plugins;
this.pluginModules = plugins.map(plugin => {
if (typeof plugin === 'function') {
return { transform: plugin };
}
return plugin.module;
});
}
}
loadPlugins(plugins) {
this.pluginBlocks = plugins;
this.pluginModules = plugins.map(plugin => {
if (typeof plugin === "function") {
return { transform: plugin };
}
log(message, messageType = 'info') {
if (this.runtimeParameters.quiet) {
return;
}
return plugin.module;
});
}
const oraMethod = ['succeed', 'fail', 'warn', 'info'].includes(messageType) ? messageType : 'info';
log(message, messageType = "info") {
if (this.runtimeParameters.quiet) {
return;
return ora(message)[oraMethod]();
}
const oraMethod = ["succeed", "fail", "warn", "info"].includes(messageType)
? messageType
: "info";
logFromPlugin(message, messageType) {
this.log(`${message}`, messageType);
}
return ora(message)[oraMethod]();
}
parsePluginOptions(plugin, optionsFromConfig) {
const { options: optionsSchema = {} } = plugin;
logFromPlugin(message, messageType) {
this.log(`${message}`, messageType);
}
const defaults = {};
const overrides = {};
parsePluginOptions(plugin, optionsFromConfig) {
const { options: optionsSchema = {} } = plugin;
Object.keys(optionsSchema).forEach(key => {
if (optionsSchema[key].default !== undefined) {
defaults[key] = optionsSchema[key].default;
}
const defaults = {};
const overrides = {};
if (
typeof optionsSchema[key].runtimeParameter === 'string' &&
this.runtimeParameters[optionsSchema[key].runtimeParameter] !== undefined
) {
overrides[key] = this.runtimeParameters[optionsSchema[key].runtimeParameter];
}
});
Object.keys(optionsSchema).forEach(key => {
if (optionsSchema[key].default !== undefined) {
defaults[key] = optionsSchema[key].default;
}
return Object.assign({}, defaults, optionsFromConfig, overrides);
}
if (
typeof optionsSchema[key].runtimeParameter === "string" &&
this.runtimeParameters[optionsSchema[key].runtimeParameter] !==
undefined
) {
overrides[key] = this.runtimeParameters[
optionsSchema[key].runtimeParameter
];
}
});
saveContextToCache() {
if (!this.isCacheEnabled) return;
return Object.assign({}, defaults, optionsFromConfig, overrides);
}
const serializedCache = JSON.stringify(this.context);
saveContextToCache() {
if (!this.isCacheEnabled) return;
try {
fs.writeFileSync(this.cacheFilePath, serializedCache);
} catch (error) {
this.debug(error);
}
}
const serializedCache = JSON.stringify(this.context);
setContextForNamespace(namespace, data) {
this.context[namespace] = { ...this.context[namespace], ...data };
}
try {
fs.writeFileSync(this.cacheFilePath, serializedCache);
} catch (error) {
this.debug(error);
setOptionsForPluginAtIndex(index, options) {
this.pluginBlocks[index].options = options;
}
}
setContextForNamespace(namespace, data) {
this.context[namespace] = { ...this.context[namespace], ...data };
}
async transform() {
if (this.isBootstrapping || this.isTransforming) {
if (this.isTransforming) {
this.isTransformQueued = true;
}
setOptionsForPluginAtIndex(index, options) {
this.pluginBlocks[index].options = options;
}
return;
}
async transform() {
if (this.isBootstrapping || this.isTransforming) {
if (this.isTransforming) {
this.isTransformQueued = true;
}
this.isTransforming = true;
return;
}
const initialData = {
files: [],
models: [],
objects: []
};
const contextSnapshot = cloneDeep(this.context);
this.isTransforming = true;
this.pluginBlocks.forEach((pluginBlock, index) => {
const plugin = this.pluginModules[index];
const pluginName = this.getNameOfPluginAtIndex(index);
const initialData = {
files: [],
models: [],
objects: []
};
const contextSnapshot = cloneDeep(this.context);
const onTransformEndCallbacks = [];
const queue = this.pluginBlocks.reduce((queue, pluginBlock, index) => {
// If the plugin hasn't been bootstrapped, we don't want to run its
// transform method just yet.
if (!pluginBlock._isBootstrapped) {
return queue;
}
if (typeof plugin.onTransformStart === 'function') {
plugin.onTransformStart({
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: () => contextSnapshot[pluginName] || {},
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, pluginBlock.options)
});
}
});
return queue.then(data => {
const plugin = this.pluginModules[index];
const pluginName = this.getNameOfPluginAtIndex(index);
const onTransformEndCallbacks = [];
const queue = this.pluginBlocks.reduce((queue, pluginBlock, index) => {
// If the plugin hasn't been bootstrapped, we don't want to run its
// transform method just yet.
if (!pluginBlock._isBootstrapped) {
return queue;
}
if (typeof plugin.transform !== "function") {
return data;
}
return queue.then(data => {
const plugin = this.pluginModules[index];
const pluginName = this.getNameOfPluginAtIndex(index);
if (typeof plugin.onTransformEnd === "function") {
onTransformEndCallbacks.push({
args: {
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: () => contextSnapshot[pluginName] || {},
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, pluginBlock.options)
},
callback: plugin.onTransformEnd
});
}
if (typeof plugin.onTransformEnd === 'function') {
onTransformEndCallbacks.push({
args: {
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: () => contextSnapshot[pluginName] || {},
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, pluginBlock.options)
},
callback: plugin.onTransformEnd
});
}
return plugin.transform({
data,
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: () => contextSnapshot[pluginName] || {},
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, pluginBlock.options)
});
});
}, Promise.resolve(initialData));
if (typeof plugin.transform !== 'function') {
return data;
}
const finishTransform = () => {
this.isTransforming = false;
return plugin.transform({
data,
debug: this.getDebugMethodForPlugin(pluginName),
getPluginContext: () => contextSnapshot[pluginName] || {},
log: this.logFromPlugin.bind(this),
options: this.parsePluginOptions(plugin, pluginBlock.options)
});
});
}, Promise.resolve(initialData));
if (this.isTransformQueued) {
this.isTransformQueued = false;
const finishTransform = () => {
this.isTransforming = false;
this.transform();
}
};
if (this.isTransformQueued) {
this.isTransformQueued = false;
try {
const data = await queue;
this.transform();
}
};
finishTransform();
try {
const data = await queue;
if (Array.isArray(data.files)) {
await this.writeFiles(data.files);
}
finishTransform();
onTransformEndCallbacks.forEach(({ args, callback }) => {
callback({ ...args, data });
});
if (Array.isArray(data.files)) {
await this.writeFiles(data.files);
}
if (typeof this.onTransform === "function") {
this.onTransform(null, data);
}
onTransformEndCallbacks.forEach(({ args, callback }) => {
callback({ ...args, data });
});
return data;
} catch (error) {
this.log(
`An error occurred when processing the plugins: ${error.message}.`,
"fail"
);
if (typeof this.onTransform === 'function') {
this.onTransform(null, data);
}
this.debug(error);
return data;
} catch (error) {
this.log(`An error occurred when processing the plugins: ${error.message}.`, 'fail');
finishTransform();
this.debug(error);
if (typeof this.onTransform === "function") {
this.onTransform(error);
}
finishTransform();
if (typeof this.onTransform === 'function') {
this.onTransform(error);
}
}
}
}
writeFiles(files) {
const filesByPath = files.reduce((result, file) => {
if (!file.path || typeof file.path !== "string") {
this.log(
"One of the plugins tried to write a file but failed to provide a valid file path. Please check your configuration.",
"warn"
);
writeFiles(files) {
const filesByPath = files.reduce((result, file) => {
if (!file.path || typeof file.path !== 'string') {
this.log(
'One of the plugins tried to write a file but failed to provide a valid file path. Please check your configuration.',
'warn'
);
return result;
}
return result;
}
const fullPath = path.resolve(process.cwd(), file.path);
const fullPath = path.resolve(process.cwd(), file.path);
// If `append: true`, we'll append the content of the new writer to any
// existing content at this path. If not, we'll overwrite it.
if (result[fullPath] && file.append) {
// Ensuring the existing content for this path is an array.
result[fullPath].content = Array.isArray(result[fullPath].content)
? result[fullPath].content
: [result[fullPath].content];
result[fullPath].content.push(file.content);
} else {
result[fullPath] = file;
}
// If `append: true`, we'll append the content of the new writer to any
// existing content at this path. If not, we'll overwrite it.
if (result[fullPath] && file.append) {
// Ensuring the existing content for this path is an array.
result[fullPath].content = Array.isArray(result[fullPath].content) ? result[fullPath].content : [result[fullPath].content];
result[fullPath].content.push(file.content);
} else {
result[fullPath] = file;
}
return result;
}, {});
return result;
}, {});
// We start by deleting any files that were previously created by this plugin
// but that are not part of the site after the update.
this.fileWriterCache.forEach(filePath => {
if (!filesByPath[filePath]) {
try {
fs.unlinkSync(filePath);
// We start by deleting any files that were previously created by this plugin
// but that are not part of the site after the update.
this.fileWriterCache.forEach(filePath => {
if (!filesByPath[filePath]) {
try {
fs.unlinkSync(filePath);
this.log(`Deleted ${filePath}`, "info");
} catch (error) {
this.debug(error);
this.log(`Could not delete ${filePath}`, "fail");
}
}
});
this.log(`Deleted ${filePath}`, 'info');
} catch (error) {
this.debug(error);
this.log(`Could not delete ${filePath}`, 'fail');
}
}
});
this.fileWriterCache = Object.keys(filesByPath);
this.fileWriterCache = Object.keys(filesByPath);
// Now we write all the files that need to be created.
const queue = Object.keys(filesByPath).map(async filePath => {
const file = filesByPath[filePath];
const writerFunction = FILE_WRITERS[file.format];
// Now we write all the files that need to be created.
const queue = Object.keys(filesByPath).map(async filePath => {
const file = filesByPath[filePath];
const writerFunction = FILE_WRITERS[file.format];
if (typeof writerFunction !== "function") {
this.log(
`Could not create ${filePath}. "${file.format}" is not a supported format.`,
"fail"
);
if (typeof writerFunction !== 'function') {
this.log(`Could not create ${filePath}. "${file.format}" is not a supported format.`, 'fail');
return;
}
return;
}
// Ensuring the directory exists.
mkdirp.sync(path.dirname(filePath));
// Ensuring the directory exists.
mkdirp.sync(path.dirname(filePath));
try {
await writerFunction(filePath, file.content);
try {
await writerFunction(filePath, file.content);
this.log(`Created ${filePath}`, "succeed");
this.log(`Created ${filePath}`, 'succeed');
return true;
} catch (error) {
this.debug(error);
this.log(`Could not create ${filePath}`, "fail");
return true;
} catch (error) {
this.debug(error);
this.log(`Could not create ${filePath}`, 'fail');
return false;
}
});
return false;
}
});
return Promise.all(queue);
}
return Promise.all(queue);
}
}
module.exports = Sourcebit;
{
"name": "sourcebit",
"version": "0.8.1",
"description": "Sourcebit helps developers build data-driven JAMstack sites by pulling data from any third-party resource",
"main": "index.js",
"bin": {
"sourcebit": "./bin/sourcebit.js"
},
"dependencies": {
"commander": "^4.1.1",
"debug": "^4.1.1",
"dotenv": "^8.2.0",
"lodash": "^4.17.15",
"mkdirp": "^1.0.3",
"ora": "^4.0.3",
"yaml": "^1.7.2"
},
"devDependencies": {
"husky": "^4.0.0",
"jest": "^25.1.0",
"lint-staged": "^9.5.0",
"prettier": "^1.19.1"
},
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"lint": "prettier --write \"./**/*.{js,json,jsx,md,html}\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/stackbithq/sourcebit.git"
},
"keywords": [
"headless",
"headless-cms",
"jamstack",
"ssg"
],
"author": "Stackbit",
"license": "MIT",
"bugs": {
"url": "https://github.com/stackbithq/sourcebit/issues"
},
"homepage": "https://github.com/stackbithq/sourcebit#readme",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,md,html}": [
"npm run lint",
"git add"
]
}
"name": "sourcebit",
"version": "0.9.0",
"description": "Sourcebit helps developers build data-driven JAMstack sites by pulling data from any third-party resource",
"main": "index.js",
"bin": {
"sourcebit": "./bin/sourcebit.js"
},
"dependencies": {
"commander": "^4.1.1",
"debug": "^4.1.1",
"dotenv": "^8.2.0",
"lodash": "^4.17.15",
"mkdirp": "^1.0.3",
"ora": "^4.0.3",
"yaml": "^1.7.2"
},
"devDependencies": {
"@stackbit/prettier-config": "^1.0.0",
"husky": "^4.0.0",
"jest": "^25.1.0",
"lint-staged": "^9.5.0",
"prettier": "^1.19.1"
},
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"lint": "prettier --write \"./**/*.{js,json,jsx,md,html}\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/stackbithq/sourcebit.git"
},
"keywords": [
"headless",
"headless-cms",
"jamstack",
"ssg"
],
"author": "Stackbit",
"license": "MIT",
"bugs": {
"url": "https://github.com/stackbithq/sourcebit/issues"
},
"homepage": "https://github.com/stackbithq/sourcebit#readme",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,md,html}": [
"npm run lint",
"git add"
]
},
"prettier": "@stackbit/prettier-config"
}

@@ -11,15 +11,15 @@ <img alt="Sourcebit logo" src="https://raw.githubusercontent.com/stackbithq/sourcebit/master/Sourcebit.svg?sanitize=true" width="300">

- [Introduction](#introduction)
- [Getting started](#getting-started)
- [Manual installation](#manual-installation)
- [Manual configuration](#manual-configuration)
- [Usage](#usage)
- [As a CommonJS module](#as-a-commonjs-module)
- [As a command-line tool](#as-a-command-line-tool)
- [Disabling cache](#disabling-cache)
- [Plugin directory](#plugin-directory)
- [Source plugins](#source-plugins)
- [Target plugins](#target-plugins)
- [Other plugins](#other-plugins)
- [Contributing](#contributing)
- [Introduction](#introduction)
- [Getting started](#getting-started)
- [Manual installation](#manual-installation)
- [Manual configuration](#manual-configuration)
- [Usage](#usage)
- [As a CommonJS module](#as-a-commonjs-module)
- [As a command-line tool](#as-a-command-line-tool)
- [Disabling cache](#disabling-cache)
- [Plugin directory](#plugin-directory)
- [Source plugins](#source-plugins)
- [Target plugins](#target-plugins)
- [Other plugins](#other-plugins)
- [Contributing](#contributing)

@@ -34,4 +34,4 @@ ## Introduction

- _Source plugins_ are responsible for fetching data, normalizing it to a standard format, and placing the resulting entries on sets of data called _data buckets_. Subsequently, any combination of plugins may consume, transform and persist these data buckets in any way they like.
- _Target plugins_ are tasked with writing data into a format and location that other programs – such as static site generators – expect. A target plugin is not required, however. This is useful for situations where the source will be called via code, such as in a site built with tools like Next.js.
- _Source plugins_ are responsible for fetching data, normalizing it to a standard format, and placing the resulting entries on sets of data called _data buckets_. Subsequently, any combination of plugins may consume, transform and persist these data buckets in any way they like.
- _Target plugins_ are tasked with writing data into a format and location that other programs – such as static site generators – expect. A target plugin is not required, however. This is useful for situations where the source will be called via code, such as in a site built with tools like Next.js.

@@ -66,17 +66,17 @@ Read more about the [anatomy of a plugin](https://github.com/stackbithq/sourcebit/wiki/Anatomy-of-a-plugin).

module.exports = {
plugins: [
{
module: require("sourcebit-some-plugin-1"),
options: {
pluginOption1: "foo",
pluginOptino2: "bar"
}
},
{
module: require("sourcebit-some-plugin-2"),
options: {
pluginFunction1: (a, b) => a + b
}
}
]
plugins: [
{
module: require('sourcebit-some-plugin-1'),
options: {
pluginOption1: 'foo',
pluginOptino2: 'bar'
}
},
{
module: require('sourcebit-some-plugin-2'),
options: {
pluginFunction1: (a, b) => a + b
}
}
]
};

@@ -94,8 +94,8 @@ ```

```js
const sourcebit = require("sourcebit");
const config = require("./sourcebit.js");
const sourcebit = require('sourcebit');
const config = require('./sourcebit.js');
const options = {};
sourcebit.fetch(config, options).then(data => {
console.log(data);
console.log(data);
});

@@ -132,9 +132,9 @@ ```

- [Anatomy of a plugin](https://github.com/stackbithq/sourcebit/wiki/Anatomy-of-a-plugin)
- [Configuration](https://github.com/stackbithq/sourcebit/wiki/Configuration)
- [Data normalization](https://github.com/stackbithq/sourcebit/wiki/Data-normalization)
- [Debugging](https://github.com/stackbithq/sourcebit/wiki/Debugging)
- [Plugin API](https://github.com/stackbithq/sourcebit/wiki/Plugin-API)
- [Plugin registry](https://github.com/stackbithq/sourcebit/wiki/Plugin-registry)
- [Writing files to disk](https://github.com/stackbithq/sourcebit/wiki/Writing-files-to-disk)
- [Anatomy of a plugin](https://github.com/stackbithq/sourcebit/wiki/Anatomy-of-a-plugin)
- [Configuration](https://github.com/stackbithq/sourcebit/wiki/Configuration)
- [Data normalization](https://github.com/stackbithq/sourcebit/wiki/Data-normalization)
- [Debugging](https://github.com/stackbithq/sourcebit/wiki/Debugging)
- [Plugin API](https://github.com/stackbithq/sourcebit/wiki/Plugin-API)
- [Plugin registry](https://github.com/stackbithq/sourcebit/wiki/Plugin-registry)
- [Writing files to disk](https://github.com/stackbithq/sourcebit/wiki/Writing-files-to-disk)

@@ -145,14 +145,16 @@ ### Plugin directory

- [`sourcebit-sample-plugin`](http://npmjs.com/package/sourcebit-sample-plugin): A sample plugin with mock data, for demonstration/educational purposes.
- [`sourcebit-source-contentful`](http://npmjs.com/package/sourcebit-source-contentful): A source plugin for [Contentful](https://www.contentful.com/).
- [`sourcebit-source-sanity`](http://npmjs.com/package/sourcebit-source-sanity): A source plugin for [Sanity](https://sanity.io/).
- [`sourcebit-sample-plugin`](http://npmjs.com/package/sourcebit-sample-plugin): A sample plugin with mock data, for demonstration/educational purposes.
- [`sourcebit-source-contentful`](http://npmjs.com/package/sourcebit-source-contentful): A source plugin for [Contentful](https://www.contentful.com/).
- [`sourcebit-source-sanity`](http://npmjs.com/package/sourcebit-source-sanity): A source plugin for [Sanity](https://sanity.io/).
- [`@kentico/sourcebit-source-kontent`](https://www.npmjs.com/package/@kentico/sourcebit-source-kontent): A source plugin for [Kontent](https://bit.ly/2yvEEWs).
#### Target plugins
- [`sourcebit-target-hugo`](http://npmjs.com/package/sourcebit-target-hugo): A target plugin for the [Hugo](https://gohugo.io/) static site generator.
- [`sourcebit-target-jekyll`](http://npmjs.com/package/sourcebit-target-jekyll): A target plugin for the [Jekyll](https://www.jekyllrb.com/) static site generator.
- [`sourcebit-target-hugo`](http://npmjs.com/package/sourcebit-target-hugo): A target plugin for the [Hugo](https://gohugo.io/) static site generator.
- [`sourcebit-target-jekyll`](http://npmjs.com/package/sourcebit-target-jekyll): A target plugin for the [Jekyll](https://www.jekyllrb.com/) static site generator.
- [`sourcebit-target-next`](https://www.npmjs.com/package/sourcebit-target-next): A target plugin for the [Next.js](https://nextjs.org/) framework.
#### Other plugins
- [`sourcebit-transform-assets`](https://github.com/stackbithq/sourcebit-transform-assets): A plugin for downloading remote assets
- [`sourcebit-transform-assets`](https://github.com/stackbithq/sourcebit-transform-assets): A plugin for downloading remote assets

@@ -159,0 +161,0 @@ ## Contributing

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc