{"id":23980780,"url":"https://github.com/fourkitchens/saucier","last_synced_at":"2026-02-24T07:10:17.769Z","repository":{"id":33579705,"uuid":"37226098","full_name":"fourkitchens/saucier","owner":"fourkitchens","description":"A Node.JS framework for helping you build headless Drupal websites.","archived":false,"fork":false,"pushed_at":"2015-08-04T21:19:34.000Z","size":170,"stargazers_count":78,"open_issues_count":3,"forks_count":2,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-08-18T06:48:18.588Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fourkitchens.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-10T22:31:42.000Z","updated_at":"2024-02-20T14:05:59.000Z","dependencies_parsed_at":"2022-09-12T17:26:39.651Z","dependency_job_id":null,"html_url":"https://github.com/fourkitchens/saucier","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/fourkitchens/saucier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fourkitchens%2Fsaucier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fourkitchens%2Fsaucier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fourkitchens%2Fsaucier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fourkitchens%2Fsaucier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fourkitchens","download_url":"https://codeload.github.com/fourkitchens/saucier/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fourkitchens%2Fsaucier/sbom","scorecard":{"id":407971,"data":{"date":"2025-08-11","repo":{"name":"github.com/fourkitchens/saucier","commit":"8f43f9f9da1396a1adc16708696a88340138446d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/2 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T21:52:49.232Z","repository_id":33579705,"created_at":"2025-08-18T21:52:49.232Z","updated_at":"2025-08-18T21:52:49.232Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279015771,"owners_count":26085748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-07T10:18:42.273Z","updated_at":"2025-10-13T14:39:16.016Z","avatar_url":"https://github.com/fourkitchens.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"```\n                       _           \n                      (_)          \n  ___  __ _ _   _  ___ _  ___ _ __ \n / __|/ _` | | | |/ __| |/ _ \\ '__|\n \\__ \\ (_| | |_| | (__| |  __/ |   \n |___/\\__,_|\\__,_|\\___|_|\\___|_|   \n                                   \n                                   \n```\n\n# Saucier \n\nSaucier is a Node.JS framework for helping you build headless Drupal websites.\n\n## Usage\n\n### Setup\n\nThere are two additional companion modules you can use when starting out, `saucier-get` and `saucier-cache`. These modules provide functionality that was previously baked directly into Saucier.\n\n```javascript\nvar env = require('./_config/env.json'),\n    https = require('https'),\n    saucierGet = require('saucier-get')( new https.Agent({ keepAlive: true}) ),\n    saucierCache = require('saucier-cache')(),\n    templates = require('./public/templates/views'),\n    saucier = require('saucier-core')(saucierGet, saucierCache, templates, {\n      logFormat: '\\033[1;32m:remote-addr -\u003e\\033[m [:date] \\033[1;35m:method :url\\033[m :http-version \\033[1;34m:status\\033[m :res[Content-Length]',\n      staticDir: 'public',\n      maxAge: '4d',\n      envConfig: env\n    });\n```\n\nIn this example we are using the default `saucier-get` and `saucier-cache` modules.\n\nSaucier has four required options to function correctly, and API compatible `saucier-get`, `saucier-cache`, a templates function, and an options object. Saucier Get/Cache are explained in their own repositories.\n\nIn this instance `templates` is a series of compiled Dust.JS templates. You can technically use any template engine/object as long as it supports a `render()` function.\n\nThe following properties are expected when passing in an options object:\n\n- `logFormat` : Log Format is any [Morgan](https://www.npmjs.com/package/morgan) compatible log string. _Default is [dev](https://www.npmjs.com/package/morgan#dev)_.\n- `staticDir` : This is where your static assets will be served from. _Default is `public`_.\n\n- `maxAge` : Length of time in which to cache static assets with the client. _Default is `4d`_.\n- `envConfig` : **REQUIRED** This is an environmental configuration object.\n\n```json\n{\n  \"local\": {\n    \"environment\": \"local\",\n    \"api\": \"https://fakeapi.ssl.dev\",\n    \"ttl\": \"800\",\n    \"maxAttempts\" : 2,\n    \"retryDelay\": 100\n  }\n}\n```\n\nEach primary object should match the environment variable set at `NODE_ENV`. This defaults to `local`.\n\n- `api` : The backend API path.\n- `ttl` : The TTL attached to cache keys in Redis.\n- `maxAttempts` : The number of attempts to try when requesting data from the backend API. _Default is `2`_.\n- `retryDelay` : Delay between retrying requests to the backend API in milliseconds. _Default is `100`_.\n\n### Routes\n\nWhen creating your routes, Saucier V1 routes are compatible. The only difference is how route processors are handled. Pass the completely created Saucier object to your routes.\n\nRoutes are essentially node modules.\n\n```javascript\nmodule.exports = function attach(app) {\n  app.handleGet('/', 'example.dust', {\n    resource: ['sample'],\n    processors: {\n      sample: function (data) {\n        data.cheese = 'cake';\n        return data;\n      }\n    }\n  });\n}\n```\n\nThe function `app.handleGet()` is a wrapper for `app.get()` which supports some additional options.\n\n- `/` : The route pattern you wish to match on. Routes are processed sequentially within the file, and then sequentially in the order that they are required.\n- `example.dust` : This is the name of the template. That will be rendered for this route.\n- An options object:\n  - `resource` : An array of resources to request data from. These _names_ will be merged with the value of `api` from your `env.json`,  `https://fakeapi.ssl.dev/sample`. These resources are are processed asynchronously and will return an object containing JSON from the backend resource. \n  - `processors` : An object of functions that will modify the data. The `data` object is the response from the previously collected resources.\n\n\n### Extras\n\n- `SAUCIERRENDER` : An environment variable that can be set to return JSON instead of a rendered route. False is the only accepted value, `SAUCIERRENDER=false`\n- `DEBUG=saucier:*` : Saucier and each of it's core modules has a debug name space, `saucier:*`. Enable this to get wonderful debug output when developing your application. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffourkitchens%2Fsaucier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffourkitchens%2Fsaucier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffourkitchens%2Fsaucier/lists"}