├── .editorconfig ├── .github └── workflows │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── lerna.json ├── package.json ├── packages ├── .gitkeep ├── api-framework │ ├── .eslintrc.js │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── Frame.js │ │ ├── api-framework.js │ │ ├── headers.js │ │ ├── http.js │ │ ├── pipeline.js │ │ ├── serializers │ │ │ ├── handle.js │ │ │ ├── index.js │ │ │ ├── input │ │ │ │ ├── all.js │ │ │ │ └── index.js │ │ │ └── output │ │ │ │ └── index.js │ │ ├── utils │ │ │ ├── index.js │ │ │ └── options.js │ │ └── validators │ │ │ ├── handle.js │ │ │ ├── index.js │ │ │ └── input │ │ │ ├── all.js │ │ │ └── index.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── frame.test.js │ │ ├── headers.test.js │ │ ├── http.test.js │ │ ├── pipeline.test.js │ │ ├── serializers │ │ ├── handle.test.js │ │ └── input │ │ │ └── all.test.js │ │ ├── util │ │ └── options.test.js │ │ └── validators │ │ ├── handle.test.js │ │ └── input │ │ └── all.test.js ├── bookshelf-collision │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-collision.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-custom-query │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-custom-query.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-eager-load │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-eager-load.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-filter │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-filter.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-has-posts │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-has-posts.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-include-count │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-include-count.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-order │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-order.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-pagination │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-pagination.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ ├── pagination.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-plugins │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-plugins.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-search │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-search.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── hello.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── bookshelf-transaction-events │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── bookshelf-transaction-events.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── bookshelf-transaction-events.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── config │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── config.js │ │ └── get-config.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── config.test.js │ │ ├── fixtures │ │ ├── config.example.json │ │ └── config.testing.json │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── database-info │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── DatabaseInfo.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── DatabaseInfo.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── debug │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── debug.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── debug.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── domain-events │ ├── .eslintrc.js │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── DomainEvents.js │ │ └── index.d.ts │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ └── DomainEvents.test.js ├── elasticsearch │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── ElasticSearch.js │ │ └── ElasticSearchBunyan.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── ElasticSearch.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── email-mock-receiver │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── EmailMockReceiver.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ └── EmailMockReceiver.test.js ├── errors │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ ├── src │ │ ├── GhostError.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── utils.ts │ │ └── wrap-stack.ts │ ├── test │ │ ├── .eslintrc.js │ │ ├── errors.test.ts │ │ ├── utils.test.ts │ │ ├── utils │ │ │ ├── assertions.ts │ │ │ └── index.ts │ │ └── wrap-stack.test.ts │ └── tsconfig.json ├── express-test │ ├── .c8rc.json │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── example │ │ ├── README.md │ │ ├── app.js │ │ ├── data.json │ │ └── user.json │ ├── index.js │ ├── lib │ │ ├── Agent.js │ │ ├── ExpectRequest.js │ │ ├── Request.js │ │ └── utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── Agent.test.js │ │ ├── ExpectRequest.test.js │ │ ├── Request.test.js │ │ ├── __snapshots__ │ │ └── example-app.test.js.snap │ │ ├── example-app.test.js │ │ ├── fixtures │ │ ├── ghost-favicon.png │ │ ├── long-json-body.json │ │ └── test-file.txt │ │ ├── utils.test.js │ │ └── utils │ │ ├── index.js │ │ └── overrides.js ├── http-cache-utils │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── http-cache-utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ └── http-cache-utils.test.js ├── http-stream │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── HttpStream.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── HttpStream.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── jest-snapshot │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── SnapshotManager.js │ │ ├── jest-snapshot.js │ │ └── utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── SnapshotManager.test.js │ │ ├── __snapshots__ │ │ └── framework-expectations-test.js.snap │ │ ├── jest-snapshot.test.js │ │ ├── utils.test.js │ │ └── utils │ │ └── index.js ├── job-manager │ ├── .eslintrc.js │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── JobManager.js │ │ ├── JobsRepository.js │ │ ├── assemble-bree-job.js │ │ └── is-cron-expression.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── examples │ │ ├── graceful-shutdown.js │ │ └── scheduled-one-off.js │ │ ├── is-cron-expression.test.js │ │ ├── job-manager.test.js │ │ └── jobs │ │ ├── graceful.js │ │ ├── message.js │ │ ├── simple.js │ │ └── timed-job.js ├── logging │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── GhostLogger.js │ │ ├── logging.js │ │ └── utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── fixtures │ │ └── worker.js │ │ ├── logging.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── metrics │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── GhostMetrics.js │ │ └── metrics.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── metrics.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── mw-error-handler │ ├── .eslintrc.js │ ├── index.js │ ├── lib │ │ └── mw-error-handler.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ └── mw-error-handler.test.js ├── mw-vhost │ ├── .eslintrc.js │ ├── README.md │ ├── index.js │ ├── lib │ │ └── vhost.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ └── vhost.test.js ├── nodemailer │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── nodemailer.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── transporter.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── pretty-cli │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── pretty-cli.js │ │ ├── styles.js │ │ └── ui.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── pretty-cli.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── pretty-stream │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── PrettyStream.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── PrettyStream.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── prometheus-metrics │ ├── .eslintrc.js │ ├── README.md │ ├── package.json │ ├── src │ │ ├── MetricsServer.ts │ │ ├── PrometheusClient.ts │ │ ├── index.ts │ │ └── libraries.d.ts │ ├── test │ │ ├── .eslintrc.js │ │ ├── metrics-server.test.ts │ │ └── prometheus-client.test.ts │ └── tsconfig.json ├── promise │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── pipeline.js │ │ ├── pool.js │ │ └── sequence.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── pipeline.test.js │ │ ├── pool.test.js │ │ ├── sequence.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── request │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── request.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── request.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── root-utils │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── root-utils.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── root-utils.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── security │ ├── .eslintrc.js │ ├── index.js │ ├── lib │ │ ├── identifier.js │ │ ├── password.js │ │ ├── secret.js │ │ ├── string.js │ │ ├── tokens.js │ │ └── url.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── password.test.js │ │ ├── secret.test.js │ │ ├── string.test.js │ │ └── tokens.test.js ├── server │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── server.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── server.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── tpl │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── tpl.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── lodash.test.js │ │ ├── tpl.test.js │ │ └── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js ├── tsconfig.json ├── validator │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── is-byte-length.js │ │ ├── is-email.js │ │ ├── is-fqdn.js │ │ ├── is-ip.js │ │ ├── util │ │ │ ├── assert-string.js │ │ │ └── merge.js │ │ ├── validate.js │ │ └── validator.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── utils │ │ ├── assertions.js │ │ ├── index.js │ │ └── overrides.js │ │ ├── validate.test.js │ │ └── validator.test.js ├── version │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── version.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ ├── utils │ │ ├── assertions.js │ │ ├── index.js │ │ ├── modules.js │ │ └── overrides.js │ │ └── version.test.js ├── webhook-mock-receiver │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ └── WebhookMockReceiver.js │ ├── package.json │ └── test │ │ ├── .eslintrc.js │ │ └── WebhookMockReceiver.test.js └── zip │ ├── .eslintrc.js │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ ├── compress.js │ └── extract.js │ ├── package.json │ └── test │ ├── .eslintrc.js │ ├── fixtures │ └── test-theme │ │ ├── .well-known │ │ ├── .gitkeep │ │ └── hello.txt │ │ ├── LICENSE │ │ ├── README.md │ │ ├── assets │ │ ├── built │ │ │ ├── global.css │ │ │ ├── global.css.map │ │ │ ├── screen.css │ │ │ └── screen.css.map │ │ ├── css │ │ │ ├── .csscomb.json │ │ │ ├── csscomb.json │ │ │ ├── global.css │ │ │ └── screen.css │ │ ├── screenshot-desktop.jpg │ │ └── screenshot-mobile.jpg │ │ ├── author.hbs │ │ ├── default.hbs │ │ ├── error-404.hbs │ │ ├── error.hbs │ │ ├── gulpfile.js │ │ ├── index.hbs │ │ ├── locales │ │ ├── de.json │ │ └── en.json │ │ ├── package.json │ │ ├── page.hbs │ │ ├── partials │ │ ├── byline-multiple.hbs │ │ ├── byline-single.hbs │ │ ├── floating-header.hbs │ │ ├── icons │ │ │ ├── avatar.hbs │ │ │ ├── facebook.hbs │ │ │ ├── ghost-logo.hbs │ │ │ ├── infinity.hbs │ │ │ ├── location.hbs │ │ │ ├── point.hbs │ │ │ ├── rss.hbs │ │ │ ├── twitter.hbs │ │ │ └── website.hbs │ │ ├── post-card.hbs │ │ └── site-nav.hbs │ │ ├── post.hbs │ │ ├── tag.hbs │ │ └── yarn.lock │ ├── utils │ ├── assertions.js │ ├── index.js │ └── overrides.js │ └── zip.test.js ├── renovate.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 4 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.hbs] 14 | insert_final_newline = false 15 | 16 | [*.json] 17 | indent_size = 2 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | 22 | [*.{yml,yaml}] 23 | indent_size = 2 24 | 25 | [Makefile] 26 | indent_style = tab 27 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | - 'renovate/*' 8 | jobs: 9 | test: 10 | uses: tryghost/actions/.github/workflows/test.yml@main 11 | secrets: 12 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Framework 2 | 3 | ## Install 4 | 5 | 6 | ## Usage 7 | 8 | 9 | ## Develop 10 | 11 | This is a mono repository, managed with [lerna](https://lerna.js.org). 12 | 13 | 1. `git clone` this repo & `cd` into it as usual 14 | 2. `yarn setup` is mapped to `lerna bootstrap` 15 | - installs all external dependencies 16 | - links all internal dependencies 17 | 18 | To add a new package to the repo: 19 | - install [slimer](https://github.com/TryGhost/slimer) 20 | - run `slimer new ` 21 | 22 | 23 | ## Run 24 | 25 | - `yarn dev` 26 | 27 | 28 | ## Test 29 | 30 | - `yarn lint` run just eslint 31 | - `yarn test` run lint and tests 32 | 33 | 34 | ## Publish 35 | 36 | - `yarn ship` is an alias for `lerna publish` 37 | - Publishes all packages which have changed 38 | - Also updates any packages which depend on changed packages 39 | 40 | 41 | # Copyright & License 42 | 43 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 44 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "independent", 3 | "npmClient": "yarn", 4 | "packages": ["packages/*"], 5 | "command": { 6 | "publish": { 7 | "allowBranch": "main", 8 | "message": "Published new versions" 9 | } 10 | }, 11 | "local": { 12 | "public": "true", 13 | "repo": "https://github.com/TryGhost/framework", 14 | "scope": "@tryghost" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "repository": { 4 | "type": "git", 5 | "url": "git+https://github.com/TryGhost/framework.git" 6 | }, 7 | "author": "Ghost Foundation", 8 | "license": "MIT", 9 | "workspaces": [ 10 | "packages/*" 11 | ], 12 | "eslintIgnore": [ 13 | "**/node_modules/**" 14 | ], 15 | "scripts": { 16 | "dev": "echo \"Implement me!\"", 17 | "presetup": "yarn", 18 | "setup": "lerna bootstrap", 19 | "test": "lerna run test", 20 | "lint": "lerna run lint", 21 | "preship": "yarn test", 22 | "ship": "lerna publish --git-remote ${GHOST_UPSTREAM:-origin}" 23 | }, 24 | "devDependencies": { 25 | "eslint": "8.57.0", 26 | "eslint-plugin-ghost": "3.4.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/.gitkeep -------------------------------------------------------------------------------- /packages/api-framework/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/api-framework/index.js: -------------------------------------------------------------------------------- 1 | /** @typedef {object} PermissionsObject */ 2 | /** @typedef {boolean} PermissionsBoolean */ 3 | 4 | /** @typedef {number} StatusCodeNumber */ 5 | /** @typedef {(result: any) => number} StatusCodeFunction */ 6 | 7 | /** @typedef {object} ValidationObject */ 8 | 9 | /** 10 | * @typedef {object} ControllerMethod 11 | * @property {object} headers 12 | * @property {PermissionsBoolean | PermissionsObject} permissions 13 | * @property {string[]} [options] 14 | * @property {ValidationObject} [validation] 15 | * @property {string[]} [data] 16 | * @property {StatusCodeFunction | StatusCodeNumber} [statusCode] 17 | * @property {object} [response] 18 | * @property {function} [cache] 19 | * @property {(frame: import('./lib/Frame')) => object} [generateCacheKeyData] 20 | * @property {(frame: import('./lib/Frame')) => any} query 21 | */ 22 | 23 | /** 24 | * @typedef {Record & Record<'docName', string>} Controller 25 | */ 26 | 27 | module.exports = require('./lib/api-framework'); 28 | -------------------------------------------------------------------------------- /packages/api-framework/lib/api-framework.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get headers() { 3 | return require('./headers'); 4 | }, 5 | 6 | get http() { 7 | return require('./http'); 8 | }, 9 | 10 | get Frame() { 11 | return require('./Frame'); 12 | }, 13 | 14 | get pipeline() { 15 | return require('./pipeline'); 16 | }, 17 | 18 | get validators() { 19 | return require('./validators'); 20 | }, 21 | 22 | get serializers() { 23 | return require('./serializers'); 24 | }, 25 | 26 | get utils() { 27 | return require('./utils'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /packages/api-framework/lib/serializers/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get handle() { 3 | return require('./handle'); 4 | }, 5 | 6 | get input() { 7 | return require('./input'); 8 | }, 9 | 10 | get output() { 11 | return require('./output'); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /packages/api-framework/lib/serializers/input/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get all() { 3 | return require('./all'); 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /packages/api-framework/lib/serializers/output/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /packages/api-framework/lib/utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get options() { 3 | return require('./options'); 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /packages/api-framework/lib/utils/options.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | const {IncorrectUsageError} = require('@tryghost/errors'); 3 | 4 | /** 5 | * @description Helper function to prepare params for internal usages. 6 | * 7 | * e.g. "a,B,c" -> ["a", "b", "c"] 8 | * 9 | * @param {String} params 10 | * @return {Array} 11 | */ 12 | const trimAndLowerCase = (params) => { 13 | params = params || ''; 14 | 15 | if (_.isString(params)) { 16 | params = params.split(','); 17 | } 18 | 19 | // If we don't have an array at this point, something is wrong, so we should throw an 20 | // error to avoid trying to .map over something else 21 | if (!_.isArray(params)) { 22 | throw new IncorrectUsageError({ 23 | message: 'Params must be a string or array' 24 | }); 25 | } 26 | 27 | return params.map((item) => { 28 | return item.trim().toLowerCase(); 29 | }); 30 | }; 31 | 32 | module.exports.trimAndLowerCase = trimAndLowerCase; 33 | -------------------------------------------------------------------------------- /packages/api-framework/lib/validators/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get handle() { 3 | return require('./handle'); 4 | }, 5 | 6 | get input() { 7 | return require('./input'); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/api-framework/lib/validators/input/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get all() { 3 | return require('./all'); 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /packages/api-framework/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Collision 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-collision --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-collision` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-collision/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-collision'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-collision", 3 | "version": "0.1.48", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-collision" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | }, 30 | "dependencies": { 31 | "@tryghost/errors": "^1.3.8", 32 | "lodash": "^4.17.21", 33 | "moment-timezone": "^0.5.33" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-collision/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Custom Query 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-custom-query --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-custom-query` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-custom-query'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/lib/bookshelf-custom-query.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {import('bookshelf')} Bookshelf 3 | */ 4 | const customQueryPlug = function customQueryPlug(Bookshelf) { 5 | const Model = Bookshelf.Model.extend({ 6 | // override this on the model itself 7 | customQuery() {}, 8 | 9 | applyCustomQuery: function applyCustomQuery(options) { 10 | this.query((qb) => { 11 | this.customQuery(qb, options); 12 | }); 13 | } 14 | }); 15 | 16 | Bookshelf.Model = Model; 17 | }; 18 | 19 | module.exports = customQueryPlug; 20 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-custom-query", 3 | "version": "0.1.30", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-custom-query" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-custom-query/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Eager Load 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-eager-load --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-eager-load` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-eager-load'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-eager-load", 3 | "version": "0.1.34", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-eager-load" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | }, 30 | "dependencies": { 31 | "@tryghost/debug": "^0.1.35", 32 | "lodash": "^4.17.21" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-eager-load/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Filter 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-filter --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-filter` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-filter/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-filter'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-filter", 3 | "version": "0.5.23", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-filter" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | }, 30 | "dependencies": { 31 | "@tryghost/debug": "^0.1.35", 32 | "@tryghost/errors": "^1.3.8", 33 | "@tryghost/nql": "0.12.6", 34 | "@tryghost/tpl": "^0.1.35" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-filter/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Has Posts 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-has-posts --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-has-posts` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-has-posts'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-has-posts", 3 | "version": "0.1.35", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-has-posts" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | }, 30 | "dependencies": { 31 | "@tryghost/debug": "^0.1.35", 32 | "lodash": "^4.17.21" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-has-posts/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Include Count 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-include-count --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-include-count` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-include-count/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-include-count'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-include-count", 3 | "version": "0.3.18", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-include-count" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | }, 30 | "dependencies": { 31 | "@tryghost/debug": "^0.1.35", 32 | "lodash": "^4.17.21" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-include-count/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-order/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-order/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Order 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-order --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-order` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-order/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-order'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-order/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-order", 3 | "version": "0.1.30", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-order" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | }, 30 | "dependencies": { 31 | "lodash": "^4.17.21" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/bookshelf-order/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-order/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-order/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-order/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-order/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Pagination 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-pagination --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-pagination` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-pagination/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-pagination'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-pagination", 3 | "version": "0.1.51", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-pagination" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "rewire": "7.0.0", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@tryghost/errors": "^1.3.8", 33 | "@tryghost/tpl": "^0.1.35", 34 | "lodash": "^4.17.21" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-pagination/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Plugins 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-plugins --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-plugins` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-plugins/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-plugins'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/lib/bookshelf-plugins.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collision: require('@tryghost/bookshelf-collision'), 3 | customQuery: require('@tryghost/bookshelf-custom-query'), 4 | eagerLoad: require('@tryghost/bookshelf-eager-load'), 5 | filter: require('@tryghost/bookshelf-filter'), 6 | hasPosts: require('@tryghost/bookshelf-has-posts'), 7 | includeCount: require('@tryghost/bookshelf-include-count'), 8 | order: require('@tryghost/bookshelf-order'), 9 | pagination: require('@tryghost/bookshelf-pagination'), 10 | search: require('@tryghost/bookshelf-search'), 11 | transactionEvents: require('@tryghost/bookshelf-transaction-events') 12 | }; 13 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-plugins/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-search/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-search/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Search 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-search --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-search` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-search/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-search'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-search/lib/bookshelf-search.js: -------------------------------------------------------------------------------- 1 | const searchPlugin = function searchPlugin(Bookshelf) { 2 | const Model = Bookshelf.Model.extend({ 3 | // override this on the model itself 4 | searchQuery() {}, 5 | 6 | applySearchQuery: function applySearchQuery(options) { 7 | if (options.search) { 8 | this.query((qb) => { 9 | this.searchQuery(qb, options.search); 10 | }); 11 | } 12 | } 13 | }); 14 | 15 | Bookshelf.Model = Model; 16 | }; 17 | 18 | module.exports = searchPlugin; 19 | -------------------------------------------------------------------------------- /packages/bookshelf-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-search", 3 | "version": "0.1.30", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-search" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "mocha": "10.7.3", 27 | "should": "13.2.3", 28 | "sinon": "18.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /packages/bookshelf-search/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-search/test/hello.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Hello world', function () { 6 | it('Runs a test', function () { 7 | // TODO: Write me! 8 | 'hello'.should.eql('hello'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-search/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-search/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-search/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/README.md: -------------------------------------------------------------------------------- 1 | # Bookshelf Transaction Events 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/bookshelf-transaction-events --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/bookshelf-transaction-events` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bookshelf-transaction-events'); 2 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/lib/bookshelf-transaction-events.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a feature request in knex for 1.0. 3 | * https://github.com/tgriesser/knex/issues/1641 4 | */ 5 | module.exports = function (bookshelf) { 6 | const originalTransaction = bookshelf.transaction; 7 | 8 | bookshelf.transaction = function (cb) { 9 | return originalTransaction.bind(bookshelf)(function (t) { 10 | const originalCommit = t.commit; 11 | const originalRollback = t.rollback; 12 | 13 | t.commit = async function () { 14 | const originalReturn = await originalCommit.apply(t, arguments); 15 | t.emit('committed', true); 16 | return originalReturn; 17 | }; 18 | 19 | t.rollback = async function () { 20 | const originalReturn = await originalRollback.apply(t, arguments); 21 | t.emit('committed', false); 22 | return originalReturn; 23 | }; 24 | 25 | return cb(t); 26 | }); 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/bookshelf-transaction-events", 3 | "version": "0.2.19", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/bookshelf-transaction-events" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "knex": "3.1.0", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0", 30 | "sqlite3": "5.1.7" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/bookshelf-transaction-events/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/config/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/config/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/config/README.md: -------------------------------------------------------------------------------- 1 | # Config 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/config --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/config` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/config/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/config'); 2 | -------------------------------------------------------------------------------- /packages/config/lib/config.js: -------------------------------------------------------------------------------- 1 | const getConfig = require('./get-config'); 2 | 3 | let config; 4 | function initConfig() { 5 | if (!config) { 6 | config = getConfig(); 7 | } 8 | 9 | return config; 10 | } 11 | 12 | /** 13 | * @description Initialise nconf config object. 14 | * 15 | * The config object is cached, once it has been setup with the parent 16 | */ 17 | module.exports = initConfig(); 18 | -------------------------------------------------------------------------------- /packages/config/lib/get-config.js: -------------------------------------------------------------------------------- 1 | const nconf = require('nconf'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const rootUtils = require('@tryghost/root-utils'); 5 | 6 | const env = process.env.NODE_ENV || 'development'; 7 | 8 | module.exports = function getConfig() { 9 | const defaults = {}; 10 | const parentPath = rootUtils.getProcessRoot(); 11 | 12 | const config = new nconf.Provider(); 13 | 14 | if (parentPath && fs.existsSync(path.join(parentPath, 'config.example.json'))) { 15 | Object.assign(defaults, require(path.join(parentPath, 'config.example.json'))); 16 | } 17 | 18 | config.argv() 19 | .env({ 20 | separator: '__' 21 | }) 22 | .file({ 23 | file: path.join(parentPath, 'config.' + env + '.json') 24 | }); 25 | 26 | config.set('env', env); 27 | 28 | config.defaults(defaults); 29 | 30 | return config; 31 | }; -------------------------------------------------------------------------------- /packages/config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/config", 3 | "version": "0.2.27", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/config" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@tryghost/root-utils": "^0.3.33", 33 | "nconf": "^0.12.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/config/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/config/test/fixtures/config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello": "world", 3 | "test": "overriden" 4 | } -------------------------------------------------------------------------------- /packages/config/test/fixtures/config.testing.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": "root-config", 3 | "should-be-used": true 4 | } 5 | -------------------------------------------------------------------------------- /packages/config/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/config/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/config/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/database-info/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/database-info/README.md: -------------------------------------------------------------------------------- 1 | # Database Info 2 | 3 | `@tryghost/database-info` is a small utility for `knex` that returns information on the underlying DB connection. 4 | 5 | It currently works with SQLite, MySQL 5 & 8, and MariaDB. 6 | 7 | ## Install 8 | 9 | `npm install @tryghost/database-info --save` 10 | 11 | or 12 | 13 | `yarn add @tryghost/database-info` 14 | 15 | 16 | ## Usage 17 | 18 | 19 | ## Develop 20 | 21 | This is a mono repository, managed with [lerna](https://lernajs.io/). 22 | 23 | Follow the instructions for the top-level repo. 24 | 1. `git clone` this repo & `cd` into it as usual 25 | 2. Run `yarn` to install top-level dependencies. 26 | 27 | 28 | ## Run 29 | 30 | - `yarn dev` 31 | 32 | 33 | ## Test 34 | 35 | - `yarn lint` run just eslint 36 | - `yarn test` run lint and tests 37 | 38 | 39 | 40 | 41 | # Copyright & License 42 | 43 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/database-info/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/DatabaseInfo'); 2 | -------------------------------------------------------------------------------- /packages/database-info/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/database-info", 3 | "version": "0.3.30", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/database-info" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "knex": "3.1.0", 28 | "mocha": "10.7.3", 29 | "should": "13.2.3", 30 | "sinon": "18.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/database-info/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/database-info/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/database-info/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/database-info/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/debug/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/debug/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/debug/README.md: -------------------------------------------------------------------------------- 1 | # Debug 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/debug --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/debug` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/debug/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/debug'); 2 | -------------------------------------------------------------------------------- /packages/debug/lib/debug.js: -------------------------------------------------------------------------------- 1 | const rootUtils = require('@tryghost/root-utils'); 2 | const debug = require('debug'); 3 | 4 | /** 5 | * @description Create a debug instance based on your package.json alias/name. 6 | * 7 | * The challenge here is to figure out where your package.json exist. 8 | * 9 | * @param {String} name - Name of the debug unit. 10 | * @return {Function} 11 | */ 12 | module.exports = function initDebug(name) { 13 | const parentPath = rootUtils.getCallerRoot(); 14 | let alias; 15 | 16 | try { 17 | const pkg = require(parentPath + '/package.json'); 18 | 19 | if (pkg.alias) { 20 | alias = pkg.alias; 21 | } else { 22 | alias = pkg.name; 23 | } 24 | } catch (err) { 25 | alias = 'undefined'; 26 | } 27 | 28 | return debug(alias + ':' + name); 29 | }; 30 | 31 | module.exports._base = debug; -------------------------------------------------------------------------------- /packages/debug/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/debug", 3 | "version": "0.1.35", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/debug" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@tryghost/root-utils": "^0.3.33", 33 | "debug": "^4.3.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/debug/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/debug/test/debug.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | const debug = require('../index'); 5 | 6 | describe('debug', function () { 7 | it('Outputs the correct module name', function () { 8 | debug('test').namespace.should.eql('@tryghost/debug:test'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/debug/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/debug/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/debug/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/domain-events/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/domain-events/README.md: -------------------------------------------------------------------------------- 1 | # Domain Events 2 | 3 | ## Usage 4 | 5 | ```js 6 | const DomainEvents = require('@tryghost/domain-events'); 7 | 8 | class MyEvent { 9 | constructor(message) { 10 | this.timestamp = new Date(); 11 | this.data = { 12 | message 13 | }; 14 | } 15 | } 16 | 17 | DomainEvents.subscribe(MyEvent, function handler(event) { 18 | console.log(event.data.message); 19 | }); 20 | 21 | const event = new MyEvent('hello world'); 22 | 23 | DomainEvents.dispatch(event); 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/domain-events/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/DomainEvents'); 2 | -------------------------------------------------------------------------------- /packages/domain-events/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare type ConstructorOf = new (...args: any[]) => T 2 | -------------------------------------------------------------------------------- /packages/domain-events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/domain-events", 3 | "version": "1.0.1", 4 | "publishConfig": { 5 | "access": "public" 6 | }, 7 | "author": "Ghost Foundation", 8 | "license": "MIT", 9 | "main": "index.js", 10 | "types": "types", 11 | "scripts": { 12 | "dev": "echo \"Implement me!\"", 13 | "test:unit": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura --check-coverage --100 -- mocha --reporter dot './test/**/*.test.js'", 14 | "test": "yarn test:unit", 15 | "lint:code": "eslint *.js lib/ --ext .js --cache", 16 | "lint": "yarn lint:code && yarn lint:test", 17 | "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache" 18 | }, 19 | "files": [ 20 | "index.js", 21 | "lib" 22 | ], 23 | "devDependencies": { 24 | "@tryghost/logging": "^2.4.22", 25 | "c8": "8.0.1", 26 | "mocha": "10.8.2", 27 | "should": "13.2.3" 28 | }, 29 | "repository": { 30 | "type": "git", 31 | "url": "git+https://github.com/TryGhost/framework.git", 32 | "directory": "packages/domain-events" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/domain-events/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/elasticsearch/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/elasticsearch/README.md: -------------------------------------------------------------------------------- 1 | # Elasticsearch 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/elasticsearch --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/elasticsearch` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | # Copyright & License 37 | 38 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 39 | -------------------------------------------------------------------------------- /packages/elasticsearch/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/ElasticSearch'); 2 | module.exports.BunyanStream = require('./lib/ElasticSearchBunyan'); 3 | -------------------------------------------------------------------------------- /packages/elasticsearch/lib/ElasticSearchBunyan.js: -------------------------------------------------------------------------------- 1 | const ElasticSearch = require('./ElasticSearch'); 2 | const {PassThrough} = require('stream'); 3 | const split = require('split2'); 4 | 5 | // Create a writable stream which pipes data written into it, into the bulk helper 6 | 7 | class ElasticSearchBunyan { 8 | constructor(clientConfig, index, pipeline) { 9 | this.client = new ElasticSearch(clientConfig); 10 | this.index = index; 11 | this.pipeline = pipeline; 12 | } 13 | 14 | getStream() { 15 | const index = this.index; 16 | const pipeline = this.pipeline; 17 | const stream = new PassThrough(); 18 | this.client.client.helpers.bulk({ 19 | datasource: stream.pipe(split()), 20 | onDocument() { 21 | return { 22 | create: {_index: index} 23 | }; 24 | }, 25 | pipeline 26 | }); 27 | 28 | return stream; 29 | } 30 | } 31 | 32 | module.exports = ElasticSearchBunyan; 33 | -------------------------------------------------------------------------------- /packages/elasticsearch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/elasticsearch", 3 | "version": "3.0.24", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/elasticsearch" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@elastic/elasticsearch": "8.13.1", 33 | "@tryghost/debug": "^0.1.35", 34 | "split2": "4.2.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/elasticsearch/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/elasticsearch/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/elasticsearch/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/elasticsearch/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/email-mock-receiver/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/email-mock-receiver/README.md: -------------------------------------------------------------------------------- 1 | # Email Mock Receiver 2 | 3 | Mocks email sending method and manages snapshots for outgoing email information such as to addresses, html content of emails, etc. 4 | 5 | ## Install 6 | 7 | `npm install @tryghost/email-mock-receiver --save` 8 | 9 | or 10 | 11 | `yarn add @tryghost/email-mock-receiver` 12 | 13 | ## Usage 14 | 15 | 16 | ## Develop 17 | 18 | This is a monorepo package. 19 | 20 | Follow the instructions for the top-level repo. 21 | 1. `git clone` this repo & `cd` into it as usual 22 | 2. Run `yarn` to install top-level dependencies. 23 | 24 | 25 | 26 | ## Test 27 | 28 | - `yarn lint` run just eslint 29 | - `yarn test` run lint and tests 30 | 31 | -------------------------------------------------------------------------------- /packages/email-mock-receiver/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/EmailMockReceiver'); 2 | -------------------------------------------------------------------------------- /packages/email-mock-receiver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/email-mock-receiver", 3 | "version": "0.3.11", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/email-mock-receiver" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test:unit": "NODE_ENV=testing c8 --all --check-coverage --100 --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "test": "yarn test:unit", 16 | "lint:code": "eslint *.js lib/ --ext .js --cache", 17 | "lint": "yarn lint:code && yarn lint:test", 18 | "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache" 19 | }, 20 | "files": [ 21 | "index.js", 22 | "lib" 23 | ], 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "devDependencies": { 28 | "c8": "10.1.3", 29 | "mocha": "10.7.3", 30 | "sinon": "18.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/email-mock-receiver/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/errors/.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | cjs 3 | es 4 | types 5 | -------------------------------------------------------------------------------- /packages/errors/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/ts' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/errors/.gitignore: -------------------------------------------------------------------------------- 1 | cjs 2 | es 3 | types 4 | -------------------------------------------------------------------------------- /packages/errors/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/errors/README.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/errors --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/errors` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 40 | -------------------------------------------------------------------------------- /packages/errors/src/index.ts: -------------------------------------------------------------------------------- 1 | import {GhostError} from './GhostError'; 2 | import * as ghostErrors from './errors'; 3 | import {deserialize, isGhostError, prepareStackForUser, serialize} from './utils'; 4 | 5 | export * from './errors'; 6 | export type {GhostError}; 7 | export default ghostErrors; 8 | 9 | export const utils = { 10 | serialize, 11 | deserialize, 12 | isGhostError, 13 | prepareStackForUser 14 | }; 15 | -------------------------------------------------------------------------------- /packages/errors/src/wrap-stack.ts: -------------------------------------------------------------------------------- 1 | export function wrapStack(err: Error, internalErr: Error) { 2 | const extraLine = (err.stack?.split(/\n/g) || [])[1]; 3 | const [firstLine, ...rest] = internalErr.stack?.split(/\n/g) || []; 4 | return [firstLine, extraLine, ...rest].join('\n'); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/errors/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/ts-test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/errors/test/utils/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require assertions - adds custom should assertions 8 | import './assertions'; 9 | -------------------------------------------------------------------------------- /packages/errors/test/wrap-stack.test.ts: -------------------------------------------------------------------------------- 1 | import assert from 'assert/strict'; 2 | import {wrapStack} from '../src/wrap-stack'; 3 | 4 | describe('wrapStack', function () { 5 | it('returns combined stack lines', function () { 6 | const ghostError = new Error('I am the ghost one!'); 7 | ghostError.stack = 'ghost fn\nghost stack 1\nghost stack 2'; 8 | const internalError = new Error('I am the internal one!'); 9 | internalError.stack = 'internal fn\ninternal stack 1\ninternal stack 2'; 10 | 11 | assert.equal(wrapStack(ghostError, internalError), 'internal fn\nghost stack 1\ninternal stack 1\ninternal stack 2'); 12 | }); 13 | 14 | it('handles errors without a stack', function () { 15 | const ghostError = new Error('I am the ghost one!'); 16 | ghostError.stack = undefined; 17 | const internalError = new Error('I am the internal one!'); 18 | internalError.stack = undefined; 19 | 20 | assert.equal(wrapStack(ghostError, internalError), '\n'); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/errors/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": [ 4 | "src/**/*" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/express-test/.c8rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "all": true, 3 | "100": true, 4 | "reporter": ["text", "html", "cobertura"], 5 | "check-coverage": true 6 | } 7 | -------------------------------------------------------------------------------- /packages/express-test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/express-test/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/express-test/example/README.md: -------------------------------------------------------------------------------- 1 | # Example App 2 | 3 | This lives here, rather than in test fixtures, because if it lives inside of /test then we can't check coverage reports! 4 | We are using this to check that the express-test framework works as expected & checking coverage helps with that. 5 | 6 | This folder is NOT included in the package.json files array, and therefore should not be included in the package. 7 | Therefore express & express-session can be dev dependencies. They're not used inside of /lib. 8 | -------------------------------------------------------------------------------- /packages/express-test/example/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "foo": [{ 3 | "bar": "baz" 4 | }] 5 | } 6 | -------------------------------------------------------------------------------- /packages/express-test/example/user.json: -------------------------------------------------------------------------------- 1 | {"username": "hello", "password": "world"} 2 | -------------------------------------------------------------------------------- /packages/express-test/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/Agent'); 2 | 3 | // NOTE: exposing jest-snapshot as a part of express-test to avoid 4 | // version mismatching on the client side 5 | module.exports.snapshot = { 6 | mochaHooks: require('@tryghost/jest-snapshot').mochaHooks, 7 | snapshotManager: require('@tryghost/jest-snapshot').snapshotManager, 8 | matchSnapshotAssertion: require('@tryghost/jest-snapshot').matchSnapshotAssertion, 9 | any: require('@tryghost/jest-snapshot').any, 10 | stringMatching: require('@tryghost/jest-snapshot').stringMatching 11 | }; 12 | -------------------------------------------------------------------------------- /packages/express-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/express-test", 3 | "version": "0.14.1", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/express-test" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 mocha --require ./test/utils/overrides.js './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "express": "4.21.1", 28 | "express-session": "1.18.1", 29 | "mocha": "10.7.3", 30 | "multer": "^2.0.0", 31 | "sinon": "18.0.0" 32 | }, 33 | "dependencies": { 34 | "@tryghost/jest-snapshot": "^0.5.18", 35 | "cookiejar": "^2.1.3", 36 | "form-data": "^4.0.2", 37 | "mime-types": "^3.0.1", 38 | "reqresnext": "^1.7.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/express-test/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/express-test/test/__snapshots__/example-app.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Example App Set & Expect check body using snapshot matching errors correctly for random data 1: [body] 1`] = ` 4 | Object { 5 | "foo": "bar", 6 | "id": "0.peo1xr2fyg", 7 | } 8 | `; 9 | 10 | exports[`Example App Set & Expect check body using snapshot matching properties works for random data 1: [body] 1`] = ` 11 | Object { 12 | "foo": "bar", 13 | "id": Any, 14 | } 15 | `; 16 | 17 | exports[`Example App Set & Expect check headers, status and body using set, expect chaining & snapshot matching 1: [body] 1`] = ` 18 | Object { 19 | "foo": "bar", 20 | } 21 | `; 22 | 23 | exports[`Example App Set & Expect check headers, status and body using set, expect chaining & snapshot matching 2: [headers] 1`] = ` 24 | Object { 25 | "content-length": "13", 26 | "content-type": "application/json; charset=utf-8", 27 | "etag": "W/\\"d-pedE0BZFQNM7HX6mFsKPL6l+dUo\\"", 28 | "x-checked": "true", 29 | "x-powered-by": "Express", 30 | } 31 | `; 32 | -------------------------------------------------------------------------------- /packages/express-test/test/fixtures/ghost-favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/express-test/test/fixtures/ghost-favicon.png -------------------------------------------------------------------------------- /packages/express-test/test/fixtures/long-json-body.json: -------------------------------------------------------------------------------- 1 | {"foo":"bar","nested":{"foo":"bar"}} 2 | -------------------------------------------------------------------------------- /packages/express-test/test/fixtures/test-file.txt: -------------------------------------------------------------------------------- 1 | test content for file upload 2 | -------------------------------------------------------------------------------- /packages/express-test/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | const sinon = require('sinon'); 8 | 9 | const stubCookies = (request) => { 10 | const saveCookiesStub = request._saveCookies = sinon.stub(); 11 | const restoreCookiesStub = request._restoreCookies = sinon.stub(); 12 | return {saveCookiesStub, restoreCookiesStub}; 13 | }; 14 | 15 | // Require overrides - these add globals for tests 16 | module.exports = { 17 | sinon, 18 | assert: require('assert'), 19 | stubCookies 20 | }; 21 | -------------------------------------------------------------------------------- /packages/express-test/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | const {mochaHooks} = require('@tryghost/jest-snapshot'); 2 | exports.mochaHooks = mochaHooks; 3 | -------------------------------------------------------------------------------- /packages/http-cache-utils/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/http-cache-utils/README.md: -------------------------------------------------------------------------------- 1 | # Http Cache Utils 2 | 3 | Set of HTTP caching related utilities and constants 4 | 5 | ## Install 6 | 7 | `npm install @tryghost/http-cache-utils --save` 8 | 9 | or 10 | 11 | `yarn add @tryghost/http-cache-utils` 12 | 13 | ## Usage 14 | 15 | 16 | ## Develop 17 | 18 | This is a monorepo package. 19 | 20 | Follow the instructions for the top-level repo. 21 | 1. `git clone` this repo & `cd` into it as usual 22 | 2. Run `yarn` to install top-level dependencies. 23 | 24 | 25 | 26 | ## Test 27 | 28 | - `yarn lint` run just eslint 29 | - `yarn test` run lint and tests 30 | 31 | 32 | 33 | # Copyright & License 34 | 35 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/http-cache-utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/http-cache-utils'); 2 | -------------------------------------------------------------------------------- /packages/http-cache-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/http-cache-utils", 3 | "version": "0.1.20", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/http-cache-utils" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test:unit": "NODE_ENV=testing c8 --all --check-coverage --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "test": "yarn test:unit", 16 | "lint:code": "eslint *.js lib/ --ext .js --cache", 17 | "lint": "yarn lint:code && yarn lint:test", 18 | "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache" 19 | }, 20 | "files": [ 21 | "index.js", 22 | "lib" 23 | ], 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "devDependencies": { 28 | "c8": "10.1.3", 29 | "mocha": "10.7.3", 30 | "sinon": "18.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/http-cache-utils/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/http-stream/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/http-stream/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/http-stream/README.md: -------------------------------------------------------------------------------- 1 | # Http Stream 2 | 3 | A http stream to use alongside bunyan for logging 4 | 5 | ## Install 6 | 7 | `npm install @tryghost/http-stream --save` 8 | 9 | or 10 | 11 | `yarn add @tryghost/http-stream` 12 | 13 | 14 | ## Usage 15 | 16 | 17 | ## Develop 18 | 19 | This is a mono repository, managed with [lerna](https://lernajs.io/). 20 | 21 | Follow the instructions for the top-level repo. 22 | 1. `git clone` this repo & `cd` into it as usual 23 | 2. Run `yarn` to install top-level dependencies. 24 | 25 | 26 | ## Run 27 | 28 | - `yarn dev` 29 | 30 | 31 | ## Test 32 | 33 | - `yarn lint` run just eslint 34 | - `yarn test` run lint and tests 35 | 36 | 37 | 38 | 39 | # Copyright & License 40 | 41 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/http-stream/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/HttpStream'); 2 | -------------------------------------------------------------------------------- /packages/http-stream/lib/HttpStream.js: -------------------------------------------------------------------------------- 1 | const request = require('@tryghost/request'); 2 | const debug = require('debug')('@tryghost/http-stream'); 3 | const GhostError = require('@tryghost/errors'); 4 | 5 | class HttpStream { 6 | constructor(config) { 7 | this.config = config; 8 | } 9 | 10 | async write(data) { 11 | try { 12 | if (typeof data !== 'object') { 13 | throw new GhostError.IncorrectUsageError({message: 'Type Error: Http transport requires log data to be an object'}); 14 | } 15 | 16 | const options = { 17 | ...this.config, 18 | method: 'POST', 19 | json: data 20 | }; 21 | const {url} = options; 22 | delete options.url; 23 | 24 | return await request(url, options); 25 | } catch (error) { 26 | debug('Failed to ship log', error.message); 27 | return false; 28 | } 29 | } 30 | } 31 | 32 | module.exports = HttpStream; 33 | -------------------------------------------------------------------------------- /packages/http-stream/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/http-stream/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/http-stream/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/http-stream/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/jest-snapshot/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ], 6 | ignorePatterns: [ 7 | 'coverage' 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /packages/jest-snapshot/README.md: -------------------------------------------------------------------------------- 1 | # Jest Snapshot 2 | 3 | Tools for using jest snapshot without jest 4 | 5 | ## Install 6 | 7 | `npm install @tryghost/jest-snapshot --save` 8 | 9 | or 10 | 11 | `yarn add @tryghost/jest-snapshot` 12 | 13 | 14 | ## Usage 15 | 16 | 17 | ## Develop 18 | 19 | This is a mono repository, managed with [lerna](https://lernajs.io/). 20 | 21 | Follow the instructions for the top-level repo. 22 | 1. `git clone` this repo & `cd` into it as usual 23 | 2. Run `yarn` to install top-level dependencies. 24 | 25 | 26 | ## Run 27 | 28 | - `yarn dev` 29 | 30 | 31 | ## Test 32 | 33 | - `yarn lint` run just eslint 34 | - `yarn test` run lint and tests 35 | 36 | 37 | 38 | 39 | # Copyright & License 40 | 41 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/jest-snapshot/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/jest-snapshot'); 2 | -------------------------------------------------------------------------------- /packages/jest-snapshot/lib/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @param {String} message 4 | * @param {String} errorMessage 5 | * @returns {String} 6 | */ 7 | module.exports.makeMessageFromMatchMessage = function makeMessageFromMatchMessage(message, errorMessage) { 8 | const messageLines = message.split('\n'); 9 | messageLines.splice(0, 1, errorMessage); 10 | return messageLines.join('\n'); 11 | }; 12 | -------------------------------------------------------------------------------- /packages/jest-snapshot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/jest-snapshot", 3 | "version": "0.5.18", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/jest-snapshot" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --100 --reporter text --reporter cobertura --reporter html-spa mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@jest/expect": "^28.0.1", 33 | "@jest/expect-utils": "^28.0.1", 34 | "@tryghost/errors": "^1.3.8", 35 | "jest-snapshot": "^29.0.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/jest-snapshot/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/jest-snapshot/test/__snapshots__/framework-expectations-test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`My first test 1 1`] = ` 4 | Object { 5 | "foo": "bar", 6 | } 7 | `; 8 | 9 | exports[`My second test 1 1`] = ` 10 | Object { 11 | "bar": "baz", 12 | } 13 | `; 14 | 15 | exports[`My second test 2 1`] = ` 16 | Object { 17 | "bar": "baz", 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /packages/jest-snapshot/test/utils.test.js: -------------------------------------------------------------------------------- 1 | const {assert} = require('./utils'); 2 | 3 | const {makeMessageFromMatchMessage} = require('../lib/utils'); 4 | 5 | describe('Utils', function () { 6 | describe('makeMessageFromMatchMessage', function () { 7 | it('makeMessageFromMatchMessage', function () { 8 | assert.equal(makeMessageFromMatchMessage('remove me\nnice test', 'substitute'), 'substitute\nnice test'); 9 | }); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/jest-snapshot/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | const sinon = require('sinon'); 8 | 9 | // Require overrides - these add globals for tests 10 | module.exports = { 11 | sinon, 12 | assert: require('assert') 13 | }; 14 | -------------------------------------------------------------------------------- /packages/job-manager/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/job-manager/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/JobManager'); 2 | -------------------------------------------------------------------------------- /packages/job-manager/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/job-manager/test/examples/graceful-shutdown.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | const pWaitFor = require('p-wait-for'); 4 | const path = require('path'); 5 | const setTimeoutPromise = require('util').promisify(setTimeout); 6 | const JobManager = require('../../lib/job-manager'); 7 | 8 | const jobManager = new JobManager({ 9 | info: console.log, 10 | warn: console.log, 11 | error: console.log 12 | }); 13 | 14 | process.on('SIGINT', () => { 15 | shutdown('SIGINT'); 16 | }); 17 | 18 | async function shutdown(signal) { 19 | console.log(`shutting down via: ${signal}`); 20 | 21 | await jobManager.shutdown(); 22 | } 23 | 24 | (async () => { 25 | jobManager.addJob({ 26 | at: 'every 10 seconds', 27 | job: path.resolve(__dirname, '../jobs/graceful.js') 28 | }); 29 | 30 | await setTimeoutPromise(100); // allow job to get scheduled 31 | 32 | await pWaitFor(() => (Object.keys(jobManager.bree.workers).length === 0) && (Object.keys(jobManager.bree.intervals).length === 0)); 33 | 34 | process.exit(0); 35 | })(); 36 | -------------------------------------------------------------------------------- /packages/job-manager/test/examples/scheduled-one-off.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pWaitFor = require('p-wait-for'); 3 | const addSeconds = require('date-fns/addSeconds'); 4 | const JobManager = require('../../lib/job-manager'); 5 | 6 | const jobManager = new JobManager(console); 7 | 8 | const isJobQueueEmpty = (bree) => { 9 | return (Object.keys(bree.workers).length === 0) 10 | && (Object.keys(bree.intervals).length === 0) 11 | && (Object.keys(bree.timeouts).length === 0); 12 | }; 13 | 14 | (async () => { 15 | const dateInTenSeconds = addSeconds(new Date(), 10); 16 | 17 | jobManager.addJob({ 18 | at: dateInTenSeconds, 19 | job: path.resolve(__dirname, '../jobs/timed-job.js'), 20 | data: { 21 | ms: 2000 22 | }, 23 | name: 'one-off-scheduled-job' 24 | }); 25 | 26 | await pWaitFor(() => (isJobQueueEmpty(jobManager.bree))); 27 | 28 | process.exit(0); 29 | })(); 30 | -------------------------------------------------------------------------------- /packages/job-manager/test/is-cron-expression.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | 3 | const isCronExpression = require('../lib/is-cron-expression'); 4 | 5 | describe('Is cron expression', function () { 6 | it('valid cron expressions', function () { 7 | should(isCronExpression('* * * * * *')).be.true(); 8 | should(isCronExpression('1 * * * * *')).be.true(); 9 | should(isCronExpression('0 0 13-23 * * *'), 'Range should be 0-23').be.true(); 10 | }); 11 | 12 | it('invalid cron expressions', function () { 13 | should(isCronExpression('0 123 * * * *')).not.be.true(); 14 | should(isCronExpression('a * * * *')).not.be.true(); 15 | should(isCronExpression('* 13-24 * * *'), 'Invalid range should be 0-23').not.be.true(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/job-manager/test/jobs/message.js: -------------------------------------------------------------------------------- 1 | const {parentPort} = require('worker_threads'); 2 | 3 | setInterval(() => { }, 10); 4 | 5 | if (parentPort) { 6 | parentPort.on('message', (message) => { 7 | if (message === 'error') { 8 | throw new Error('oops'); 9 | } 10 | 11 | if (message === 'cancel') { 12 | parentPort.postMessage('cancelled'); 13 | return; 14 | } 15 | 16 | // post the message back 17 | parentPort.postMessage(`Worker received: ${message}`); 18 | parentPort.postMessage('done'); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /packages/job-manager/test/jobs/simple.js: -------------------------------------------------------------------------------- 1 | setInterval(() => process.exit(0), 10); 2 | -------------------------------------------------------------------------------- /packages/job-manager/test/jobs/timed-job.js: -------------------------------------------------------------------------------- 1 | const {isMainThread, parentPort, workerData} = require('worker_threads'); 2 | const util = require('util'); 3 | const setTimeoutPromise = util.promisify(setTimeout); 4 | 5 | const passTime = async (ms) => { 6 | if (Number.isInteger(ms)) { 7 | await setTimeoutPromise(ms); 8 | } else { 9 | await setTimeoutPromise(ms.ms); 10 | } 11 | }; 12 | 13 | if (isMainThread) { 14 | module.exports = passTime; 15 | } else { 16 | (async () => { 17 | await passTime(workerData.ms); 18 | parentPort.postMessage('done'); 19 | // alternative way to signal "finished" work (not recommended) 20 | // process.exit(); 21 | })(); 22 | } 23 | -------------------------------------------------------------------------------- /packages/logging/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/logging/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/logging/README.md: -------------------------------------------------------------------------------- 1 | # Logging 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/logging --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/logging` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/logging/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/logging'); 2 | -------------------------------------------------------------------------------- /packages/logging/lib/logging.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const {isMainThread} = require('worker_threads'); 3 | const {getProcessRoot} = require('@tryghost/root-utils'); 4 | const GhostLogger = require('./GhostLogger'); 5 | 6 | let loggingConfig; 7 | try { 8 | loggingConfig = require(path.join(getProcessRoot(), 'loggingrc')); 9 | } catch (err) { 10 | loggingConfig = {}; 11 | } 12 | 13 | if (!isMainThread) { 14 | loggingConfig.transports = ['parent']; 15 | } 16 | 17 | module.exports = new GhostLogger(loggingConfig); 18 | module.exports.GhostLogger = GhostLogger; 19 | -------------------------------------------------------------------------------- /packages/logging/lib/utils.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/logging/lib/utils.js -------------------------------------------------------------------------------- /packages/logging/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/logging/test/fixtures/worker.js: -------------------------------------------------------------------------------- 1 | const logging = require('@tryghost/logging'); 2 | 3 | logging.info('Hello!'); -------------------------------------------------------------------------------- /packages/logging/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/logging/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/logging/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/metrics/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/metrics/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/metrics/README.md: -------------------------------------------------------------------------------- 1 | # Metrics 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/metrics --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/metrics` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/metrics/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/metrics'); 2 | -------------------------------------------------------------------------------- /packages/metrics/lib/metrics.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const {getProcessRoot} = require('@tryghost/root-utils'); 3 | const GhostMetrics = require('./GhostMetrics'); 4 | 5 | // Metrics piggy-backs on logging config for transport configuration 6 | let loggingConfig; 7 | try { 8 | loggingConfig = require(path.join(getProcessRoot(), 'loggingrc')); 9 | } catch (err) { 10 | loggingConfig = {}; 11 | } 12 | 13 | module.exports = new GhostMetrics(loggingConfig); 14 | module.exports.GhostMetrics = GhostMetrics; 15 | -------------------------------------------------------------------------------- /packages/metrics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/metrics", 3 | "version": "1.0.38", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/metrics" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "rewire": "7.0.0", 29 | "should": "13.2.3", 30 | "sinon": "18.0.0" 31 | }, 32 | "dependencies": { 33 | "@tryghost/elasticsearch": "^3.0.24", 34 | "@tryghost/pretty-stream": "^0.2.0", 35 | "@tryghost/root-utils": "^0.3.33", 36 | "json-stringify-safe": "^5.0.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/metrics/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/metrics/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/metrics/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/metrics/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/mw-error-handler/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/mw-error-handler/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/mw-error-handler'); 2 | -------------------------------------------------------------------------------- /packages/mw-error-handler/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/mw-vhost/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/mw-vhost/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/vhost'); 2 | -------------------------------------------------------------------------------- /packages/mw-vhost/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/mw-vhost", 3 | "version": "1.0.1", 4 | "author": "Ghost Foundation", 5 | "license": "MIT", 6 | "main": "index.js", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "scripts": { 11 | "dev": "echo \"Implement me!\"", 12 | "test:unit": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura -- mocha --reporter dot './test/**/*.test.js'", 13 | "test": "yarn test:unit", 14 | "lint:code": "eslint *.js lib/ --ext .js --cache", 15 | "lint": "yarn lint:code && yarn lint:test", 16 | "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "devDependencies": { 23 | "c8": "8.0.1", 24 | "mocha": "10.8.2", 25 | "supertest": "6.3.4" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/TryGhost/framework.git", 30 | "directory": "packages/mw-vhost" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/mw-vhost/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/nodemailer/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/nodemailer/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/nodemailer/README.md: -------------------------------------------------------------------------------- 1 | # Nodemailer 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/nodemailer --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/nodemailer` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/nodemailer/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/nodemailer'); 2 | -------------------------------------------------------------------------------- /packages/nodemailer/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/nodemailer/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/nodemailer/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/nodemailer/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/pretty-cli/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/pretty-cli/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/pretty-cli'); 2 | -------------------------------------------------------------------------------- /packages/pretty-cli/lib/pretty-cli.js: -------------------------------------------------------------------------------- 1 | const Api = require('sywac/api'); 2 | const styles = require('./styles'); 3 | const ui = require('./ui'); 4 | /** 5 | * Pretty CLI 6 | * 7 | * A mini-module to style a sywac instance in a standard way 8 | */ 9 | 10 | // Exports a pre-configured version of sywac 11 | module.exports = Api.get() 12 | // Use help & version with short forms AND 13 | // group them into a Global Options group to keep them separate from per-command options 14 | .help('-h, --help', {group: 'Global Options:'}) 15 | .version('-v, --version', {group: 'Global Options:'}) 16 | // Load our style rules 17 | .style(styles) 18 | // Add some padding at the end 19 | .epilogue(' ') 20 | // If no command is passed, output the help menu 21 | .showHelpByDefault(); 22 | 23 | // Expose a clean version, just in case 24 | module.exports.Api = Api; 25 | 26 | // Export the styles 27 | module.exports.styles = styles; 28 | 29 | // Export our ui tools 30 | module.exports.ui = ui; 31 | -------------------------------------------------------------------------------- /packages/pretty-cli/lib/styles.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | 3 | module.exports = { 4 | // Usage: script [options] etc 5 | usagePrefix: (str) => { 6 | return chalk.yellow(str.slice(0, 6)) + '\n ' + str.slice(7); 7 | }, 8 | // Options: Arguments: etc 9 | group: str => chalk.yellow(str), 10 | // --help etc 11 | flags: str => chalk.green(str), 12 | // [required] [boolean] etc 13 | hints: str => chalk.dim(str), 14 | // Use different style when a type is invalid 15 | groupError: str => chalk.red(str), 16 | flagsError: str => chalk.red(str), 17 | descError: str => chalk.yellow(str), 18 | hintsError: str => chalk.red(str), 19 | // style error messages 20 | messages: str => chalk.red(str) 21 | }; 22 | -------------------------------------------------------------------------------- /packages/pretty-cli/lib/ui.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const log = (...args) => console.log(...args); // eslint-disable-line no-console 3 | 4 | module.exports.log = log; 5 | 6 | module.exports.log.ok = (...args) => { 7 | log(chalk.green('ok'), ...args); 8 | }; 9 | 10 | module.exports.log.trace = (...args) => { 11 | log(chalk.gray('trace'), ...args); 12 | }; 13 | 14 | module.exports.log.debug = (...args) => { 15 | log(chalk.gray('debug'), ...args); 16 | }; 17 | 18 | module.exports.log.info = (...args) => { 19 | log(chalk.cyan('info'), ...args); 20 | }; 21 | 22 | module.exports.log.warn = (...args) => { 23 | log(chalk.magenta('warn'), ...args); 24 | }; 25 | 26 | module.exports.log.error = (...args) => { 27 | log(chalk.red('error'), ...args); 28 | }; 29 | 30 | module.exports.log.fatal = (...args) => { 31 | log(chalk.inverse('fatal'), ...args); 32 | }; 33 | -------------------------------------------------------------------------------- /packages/pretty-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/pretty-cli", 3 | "version": "1.2.47", 4 | "description": "A mini-module to style a sywac instance in a standard way", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/TryGhost/framework.git", 8 | "directory": "packages/pretty-cli" 9 | }, 10 | "author": "Ghost Foundation", 11 | "license": "MIT", 12 | "main": "index.js", 13 | "scripts": { 14 | "dev": "echo \"Implement me!\"", 15 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 16 | "lint": "eslint . --ext .js --cache", 17 | "posttest": "yarn lint" 18 | }, 19 | "files": [ 20 | "index.js", 21 | "lib" 22 | ], 23 | "publishConfig": { 24 | "access": "public" 25 | }, 26 | "devDependencies": { 27 | "c8": "10.1.3", 28 | "mocha": "10.7.3", 29 | "should": "13.2.3", 30 | "sinon": "18.0.0" 31 | }, 32 | "dependencies": { 33 | "chalk": "^4.1.0", 34 | "sywac": "^1.3.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/pretty-cli/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/pretty-cli/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/pretty-cli/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/pretty-cli/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/pretty-stream/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/pretty-stream/README.md: -------------------------------------------------------------------------------- 1 | # Pretty Stream 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/pretty-stream --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/pretty-stream` 10 | 11 | 12 | ## Usage 13 | 14 | Used by `@tryghost/logging` and `@tryghost/metrics`. 15 | 16 | ## Develop 17 | 18 | This is a mono repository, managed with [lerna](https://lernajs.io/). 19 | 20 | Follow the instructions for the top-level repo. 21 | 1. `git clone` this repo & `cd` into it as usual 22 | 2. Run `yarn` to install top-level dependencies. 23 | 24 | 25 | ## Run 26 | 27 | - `yarn dev` 28 | 29 | 30 | ## Test 31 | 32 | - `yarn lint` run just eslint 33 | - `yarn test` run lint and tests 34 | 35 | 36 | 37 | 38 | # Copyright & License 39 | 40 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/pretty-stream/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/PrettyStream'); 2 | -------------------------------------------------------------------------------- /packages/pretty-stream/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/pretty-stream", 3 | "version": "0.2.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/pretty-stream" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "date-format": "^4.0.14", 33 | "lodash": "^4.17.21", 34 | "prettyjson": "^1.2.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/pretty-stream/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/pretty-stream/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/pretty-stream/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/pretty-stream/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/prometheus-metrics/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['ghost'], 4 | extends: [ 5 | 'plugin:ghost/node' 6 | ] 7 | }; 8 | -------------------------------------------------------------------------------- /packages/prometheus-metrics/README.md: -------------------------------------------------------------------------------- 1 | # Metrics Server 2 | 3 | A standalone server for exporting prometheus metrics from Ghost 4 | 5 | 6 | ## Usage 7 | 8 | 9 | ## Develop 10 | 11 | This is a monorepo package. 12 | 13 | Follow the instructions for the top-level repo. 14 | 1. `git clone` this repo & `cd` into it as usual 15 | 2. Run `yarn` to install top-level dependencies. 16 | 17 | 18 | 19 | ## Test 20 | 21 | - `yarn lint` run just eslint 22 | - `yarn test` run lint and tests 23 | 24 | -------------------------------------------------------------------------------- /packages/prometheus-metrics/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MetricsServer'; 2 | export * from './PrometheusClient'; 3 | -------------------------------------------------------------------------------- /packages/prometheus-metrics/src/libraries.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@tryghost/debug'; 2 | declare module '@tryghost/logging'; -------------------------------------------------------------------------------- /packages/prometheus-metrics/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['ghost'], 4 | extends: [ 5 | 'plugin:ghost/test' 6 | ] 7 | }; 8 | -------------------------------------------------------------------------------- /packages/promise/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/promise/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/promise/README.md: -------------------------------------------------------------------------------- 1 | # Promise 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/promise --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/promise` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 40 | -------------------------------------------------------------------------------- /packages/promise/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get pipeline() { 3 | return require('./lib/pipeline'); 4 | }, 5 | 6 | get sequence() { 7 | return require('./lib/sequence'); 8 | }, 9 | 10 | get pool() { 11 | return require('./lib/pool'); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /packages/promise/lib/pipeline.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @callback Task 3 | * @param {...any} args 4 | * @returns {Promise} 5 | */ 6 | 7 | /** 8 | * Execute a series of async functions, passing the results of each to the next 9 | * @param {Task[]} tasks Set of tasks to complete in sequence 10 | * @param {...any} args Arguments for the first task, can be promises which will be resolved 11 | * @returns {Promise} 12 | */ 13 | async function pipeline(tasks, ...args) { 14 | let results = await Promise.all(args); 15 | for (const task of tasks) { 16 | results = await task.apply(null, Array.isArray(results) ? results : [results]); 17 | } 18 | return results; 19 | } 20 | 21 | module.exports = pipeline; 22 | -------------------------------------------------------------------------------- /packages/promise/lib/pool.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Promise Pool 3 | * 4 | * The pool will execute all the tasks with maxConcurrent tasks 5 | * running simoultaneously at most. 6 | */ 7 | 8 | async function pool(tasks, maxConcurrent) { 9 | if (maxConcurrent < 1) { 10 | // eslint-disable-next-line ghost/ghost-custom/no-native-error 11 | throw new Error('Must set at least 1 concurrent workers'); // eslint-disable-line no-restricted-syntax 12 | } 13 | 14 | const taskIterator = tasks.entries(); 15 | const results = []; 16 | 17 | const workers = Array(maxConcurrent).fill(taskIterator).map( 18 | async (workerIterator) => { 19 | for (let [index, task] of workerIterator) { 20 | results[index] = await task(); 21 | } 22 | } 23 | ); 24 | await Promise.all(workers); 25 | return results; 26 | } 27 | 28 | module.exports = pool; 29 | -------------------------------------------------------------------------------- /packages/promise/lib/sequence.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @callback Task 3 | * @param {...any} args 4 | * @returns {Promise} 5 | */ 6 | 7 | /** 8 | * Executes a series of asyncronous tasks in sequence 9 | * @param {Task[]} tasks Set of tasks to complete in sequence 10 | * @param {...any} args Arguments for the task 11 | * @returns {Promise} Set of results for each task, in same order as input 12 | */ 13 | async function sequence(tasks, ...args) { 14 | const results = []; 15 | for (const task of tasks) { 16 | results.push(await task.apply(this, args)); 17 | } 18 | return results; 19 | } 20 | 21 | module.exports = sequence; 22 | -------------------------------------------------------------------------------- /packages/promise/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/promise", 3 | "version": "0.3.15", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/promise" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/promise/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/promise/test/sequence.test.js: -------------------------------------------------------------------------------- 1 | require('./utils'); 2 | const sinon = require('sinon'); 3 | const {sequence} = require('../'); 4 | 5 | describe('Unit: lib/promise/sequence', function () { 6 | afterEach(function () { 7 | sinon.restore(); 8 | }); 9 | 10 | it('mixed tasks: promise and none promise', function () { 11 | const tasks = [ 12 | function a() { 13 | return Promise.resolve('hello'); 14 | }, 15 | function b() { 16 | return 'from'; 17 | }, 18 | function c() { 19 | return Promise.resolve('chio'); 20 | } 21 | ]; 22 | return sequence(tasks) 23 | .then(function (result) { 24 | result.should.eql(['hello','from', 'chio']); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/promise/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/promise/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/promise/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/request/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/request/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/request/README.md: -------------------------------------------------------------------------------- 1 | # Request 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/request --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/request` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/request/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/request'); 2 | -------------------------------------------------------------------------------- /packages/request/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/request/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/request/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/request/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/root-utils/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/root-utils/README.md: -------------------------------------------------------------------------------- 1 | # Root Utils 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/root-utils --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/root-utils` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/root-utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/root-utils'); 2 | -------------------------------------------------------------------------------- /packages/root-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/root-utils", 3 | "version": "0.3.33", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/root-utils" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "caller": "^1.0.1", 33 | "find-root": "^1.1.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/root-utils/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/root-utils/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/root-utils/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/root-utils/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/security/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/security/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | get url() { 3 | return require('./lib/url'); 4 | }, 5 | 6 | get tokens() { 7 | return require('./lib/tokens'); 8 | }, 9 | 10 | get string() { 11 | return require('./lib/string'); 12 | }, 13 | 14 | get identifier() { 15 | return require('./lib/identifier'); 16 | }, 17 | 18 | get password() { 19 | return require('./lib/password'); 20 | }, 21 | 22 | get secret() { 23 | return require('./lib/secret'); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /packages/security/lib/identifier.js: -------------------------------------------------------------------------------- 1 | let _private = {}; 2 | 3 | _private.getRandomInt = function (min, max) { 4 | return Math.floor(Math.random() * (max - min + 1)) + min; 5 | }; 6 | 7 | /** 8 | * Return a unique identifier with the given `len`. 9 | * 10 | * @deprecated use secret.create() instead 11 | * @param {Number} maxLength 12 | * @return {String} 13 | */ 14 | module.exports.uid = function uid(maxLength) { 15 | const buf = []; 16 | const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 17 | const charLength = chars.length; 18 | let i; 19 | 20 | for (i = 0; i < maxLength; i = i + 1) { 21 | buf.push(chars[_private.getRandomInt(0, charLength - 1)]); 22 | } 23 | 24 | return buf.join(''); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/security/lib/password.js: -------------------------------------------------------------------------------- 1 | const bcrypt = require('bcryptjs'); 2 | 3 | let HASH_ROUNDS = 10; 4 | 5 | if (process.env.NODE_ENV?.startsWith('testing')) { 6 | HASH_ROUNDS = 1; 7 | } 8 | 9 | module.exports.hash = async function hash(plainPassword) { 10 | const salt = await bcrypt.genSalt(HASH_ROUNDS); 11 | return bcrypt.hash(plainPassword, salt); 12 | }; 13 | 14 | module.exports.compare = function compare(plainPassword, hashedPassword) { 15 | return bcrypt.compare(plainPassword, hashedPassword); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/security/lib/string.js: -------------------------------------------------------------------------------- 1 | const slugify = require('@tryghost/string').slugify; 2 | 3 | /** 4 | * @param {string} string 5 | * @param {{importing?: boolean}} [options] 6 | */ 7 | module.exports.safe = function safe(string, options = {}) { 8 | return slugify(string, {requiredChangesOnly: options.importing === true}); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/security/lib/url.js: -------------------------------------------------------------------------------- 1 | // The token is encoded URL safe by replacing '+' with '-', '\' with '_' and removing '=' 2 | // NOTE: the token is not encoded using valid base64 anymore 3 | module.exports.encodeBase64 = function encodeBase64(base64String) { 4 | return base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); 5 | }; 6 | 7 | // Decode url safe base64 encoding and add padding ('=') 8 | module.exports.decodeBase64 = function decodeBase64(base64String) { 9 | base64String = base64String.replace(/-/g, '+').replace(/_/g, '/'); 10 | while (base64String.length % 4) { 11 | base64String += '='; 12 | } 13 | return base64String; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/security/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/security", 3 | "version": "1.0.1", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/security" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "publishConfig": { 13 | "access": "public" 14 | }, 15 | "scripts": { 16 | "dev": "echo \"Implement me!\"", 17 | "test:unit": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura -- mocha --reporter dot './test/**/*.test.js'", 18 | "test": "yarn test:unit", 19 | "lint:code": "eslint *.js lib/ --ext .js --cache", 20 | "lint": "yarn lint:code && yarn lint:test", 21 | "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache" 22 | }, 23 | "files": [ 24 | "index.js", 25 | "lib" 26 | ], 27 | "devDependencies": { 28 | "c8": "8.0.1", 29 | "mocha": "10.8.2", 30 | "should": "13.2.3", 31 | "sinon": "15.2.0", 32 | "uuid": "9.0.1" 33 | }, 34 | "dependencies": { 35 | "@tryghost/string": "0.2.15", 36 | "bcryptjs": "2.4.3" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/security/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/security/test/password.test.js: -------------------------------------------------------------------------------- 1 | require('should'); 2 | const security = require('../'); 3 | 4 | describe('Lib: Security - Password', function () { 5 | it('hash plain password', function () { 6 | return security.password.hash('test') 7 | .then(function (hash) { 8 | hash.should.match(/^\$2[ayb]\$.{56}$/); 9 | }); 10 | }); 11 | 12 | it('compare password', function () { 13 | return security.password.compare('test', '$2a$10$we16f8rpbrFZ34xWj0/ZC.LTPUux8ler7bcdTs5qIleN6srRHhilG') 14 | .then(function (valid) { 15 | valid.should.be.true; 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/server/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/server/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/server/README.md: -------------------------------------------------------------------------------- 1 | # Server 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/server --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/server` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/server/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/server'); 2 | -------------------------------------------------------------------------------- /packages/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/server", 3 | "version": "0.1.52", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/server" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@tryghost/debug": "^0.1.35", 33 | "@tryghost/logging": "^2.4.22" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/server/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/server/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/server/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/server/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/tpl/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/tpl/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/tpl/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/tpl'); 2 | -------------------------------------------------------------------------------- /packages/tpl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/tpl", 3 | "version": "0.1.35", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/tpl" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --100 --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "lodash.template": "^4.5.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/tpl/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/tpl/test/lodash.test.js: -------------------------------------------------------------------------------- 1 | // Switch these lines once there are useful utils 2 | // const testUtils = require('./utils'); 3 | require('./utils'); 4 | 5 | describe('Lodash Template', function () { 6 | it('Does not get clobbered by this lib', function () { 7 | require('../lib/tpl'); 8 | let _ = require('lodash'); 9 | 10 | // @ts-ignore 11 | _.templateSettings.interpolate.should.eql(/<%=([\s\S]+?)%>/g); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/tpl/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/tpl/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/tpl/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/validator/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/validator/README.md: -------------------------------------------------------------------------------- 1 | # Validator 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/validator --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/validator` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /packages/validator/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/validator'); 2 | module.exports.validate = require('./lib/validate'); 3 | -------------------------------------------------------------------------------- /packages/validator/lib/is-byte-length.js: -------------------------------------------------------------------------------- 1 | const assertString = require('./util/assert-string'); 2 | 3 | /* eslint-disable prefer-rest-params */ 4 | module.exports = function isByteLength(str, options) { 5 | assertString(str); 6 | let min; 7 | let max; 8 | if (typeof (options) === 'object') { 9 | min = options.min || 0; 10 | max = options.max; 11 | } else { // backwards compatibility: isByteLength(str, min [, max]) 12 | min = arguments[1]; 13 | max = arguments[2]; 14 | } 15 | const len = encodeURI(str).split(/%..|./).length - 1; 16 | return len >= min && (typeof max === 'undefined' || len <= max); 17 | }; 18 | -------------------------------------------------------------------------------- /packages/validator/lib/util/assert-string.js: -------------------------------------------------------------------------------- 1 | const errors = require('@tryghost/errors'); 2 | 3 | /** 4 | * This file is a copy of validator.js assertString util - v13.7.0: 5 | * https://github.com/validatorjs/validator.js/blob/531dc7f1f75613bec75c6d888b46480455e78dc7/src/lib/util/assertString.js 6 | */ 7 | module.exports = function assertString(input) { 8 | const isString = typeof input === 'string' || input instanceof String; 9 | 10 | if (!isString) { 11 | let invalidType = typeof input; 12 | if (input === null) { 13 | invalidType = 'null'; 14 | } else if (invalidType === 'object') { 15 | invalidType = input.constructor.name; 16 | } 17 | 18 | throw new errors.ValidationError({ 19 | message: `Expected a string but received a ${invalidType}` 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /packages/validator/lib/util/merge.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is a copy of validator.js merge util - v13.7.0: 3 | * https://github.com/validatorjs/validator.js/blob/531dc7f1f75613bec75c6d888b46480455e78dc7/src/lib/util/merge.js 4 | */ 5 | 6 | module.exports = function merge(obj = {}, defaults) { 7 | for (const key in defaults) { 8 | if (typeof obj[key] === 'undefined') { 9 | obj[key] = defaults[key]; 10 | } 11 | } 12 | return obj; 13 | }; 14 | -------------------------------------------------------------------------------- /packages/validator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/validator", 3 | "version": "0.2.17", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/validator" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "should": "13.2.3", 29 | "sinon": "18.0.0" 30 | }, 31 | "dependencies": { 32 | "@tryghost/errors": "^1.3.8", 33 | "@tryghost/tpl": "^0.1.35", 34 | "lodash": "^4.17.21", 35 | "moment-timezone": "^0.5.23", 36 | "validator": "7.2.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/validator/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/validator/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/validator/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/validator/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/validator/test/validate.test.js: -------------------------------------------------------------------------------- 1 | require('./utils'); 2 | 3 | const validator = require('../'); 4 | 5 | // Validate our customizations 6 | describe('Validate', function () { 7 | it('should export our required functions', function () { 8 | should.exist(validator); 9 | 10 | validator.should.have.properties( 11 | ['validate'] 12 | ); 13 | 14 | validator.validate.should.be.a.Function(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/version/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/version/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/version/README.md: -------------------------------------------------------------------------------- 1 | # Ghost Version 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/version --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/version` 10 | 11 | 12 | ## Usage 13 | 14 | 15 | ## Develop 16 | 17 | This is a mono repository, managed with [lerna](https://lernajs.io/). 18 | 19 | Follow the instructions for the top-level repo. 20 | 1. `git clone` this repo & `cd` into it as usual 21 | 2. Run `yarn` to install top-level dependencies. 22 | 23 | 24 | ## Run 25 | 26 | - `yarn dev` 27 | 28 | 29 | ## Test 30 | 31 | - `yarn lint` run just eslint 32 | - `yarn test` run lint and tests 33 | 34 | 35 | 36 | 37 | # Copyright & License 38 | 39 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 40 | -------------------------------------------------------------------------------- /packages/version/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/version'); 2 | -------------------------------------------------------------------------------- /packages/version/lib/version.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const semver = require('semver'); 3 | const rootUtils = require('@tryghost/root-utils'); 4 | const packageInfo = require(path.join(rootUtils.getProcessRoot(), 'package.json')); 5 | const version = packageInfo.version; 6 | const plainVersion = version.match(/^(\d+\.)?(\d+\.)?(\d+)/)[0]; 7 | 8 | let _private = {}; 9 | 10 | _private.compose = function compose(type) { 11 | switch (type) { 12 | case 'pre': 13 | return plainVersion + '-' + semver.prerelease(version).join('.'); 14 | default: 15 | return version; 16 | } 17 | }; 18 | 19 | // major.minor 20 | module.exports.safe = version.match(/^(\d+\.)?(\d+)/)[0]; 21 | 22 | // major.minor.patch-{prerelease} 23 | module.exports.full = semver.prerelease(version) ? _private.compose('pre') : plainVersion; 24 | 25 | // original string in package.json (can contain pre-release and build suffix) 26 | module.exports.original = version; -------------------------------------------------------------------------------- /packages/version/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/version", 3 | "version": "0.1.33", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/version" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "mocha": "10.7.3", 28 | "rewire": "7.0.0", 29 | "should": "13.2.3", 30 | "sinon": "18.0.0" 31 | }, 32 | "dependencies": { 33 | "@tryghost/root-utils": "^0.3.33", 34 | "semver": "^7.3.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/version/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/version/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/version/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | 13 | // Custom module mocking code 14 | const modules = require('./modules'); 15 | 16 | module.exports = Object.assign({}, modules); 17 | -------------------------------------------------------------------------------- /packages/version/test/utils/modules.js: -------------------------------------------------------------------------------- 1 | const Module = require('module'); 2 | const originalRequireFn = Module.prototype.require; 3 | 4 | /** 5 | * helper fn to mock non-existent modules 6 | * mockNonExistentModule(/pattern/, mockedModule) 7 | */ 8 | exports.mockNonExistentModule = (modulePath, module, error = false) => { 9 | Module.prototype.require = function (path) { 10 | if (path.match(modulePath)) { 11 | if (error) { 12 | throw module; 13 | } 14 | return module; 15 | } 16 | 17 | return originalRequireFn.apply(this, arguments); 18 | }; 19 | }; 20 | 21 | exports.unmockNonExistentModule = () => { 22 | Module.prototype.require = originalRequireFn; 23 | }; -------------------------------------------------------------------------------- /packages/version/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /packages/webhook-mock-receiver/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/webhook-mock-receiver/README.md: -------------------------------------------------------------------------------- 1 | # Webhook Mock Receiver 2 | 3 | Up to date documentation about the usage of the module available in [End-to-end Testing Codex](https://ghost.notion.site/End-to-end-Testing-6a2ef073b1754b18aff42e24a632a007#827471b6314640758460b9c1e22b34c4). 4 | 5 | ## Install 6 | 7 | `npm install @tryghost/webhook-mock-receiver --save` 8 | 9 | or 10 | 11 | `yarn add @tryghost/webhook-mock-receiver` 12 | 13 | 14 | ## Usage 15 | 16 | 17 | ## Develop 18 | 19 | This is a mono repository, managed with [lerna](https://lernajs.io/). 20 | 21 | Follow the instructions for the top-level repo. 22 | 1. `git clone` this repo & `cd` into it as usual 23 | 2. Run `yarn` to install top-level dependencies. 24 | 25 | 26 | ## Run 27 | 28 | - `yarn dev` 29 | 30 | 31 | ## Test 32 | 33 | - `yarn lint` run just eslint 34 | - `yarn test` run lint and tests 35 | 36 | 37 | 38 | 39 | # Copyright & License 40 | 41 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 42 | -------------------------------------------------------------------------------- /packages/webhook-mock-receiver/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/WebhookMockReceiver'); 2 | -------------------------------------------------------------------------------- /packages/webhook-mock-receiver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/webhook-mock-receiver", 3 | "version": "0.2.17", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/webhook-mock-receiver" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --check-coverage --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint:code": "eslint *.js lib/ --ext .js --cache", 16 | "lint": "yarn lint:code && yarn lint:test", 17 | "lint:test": "eslint -c test/.eslintrc.js test/ --ext .js --cache", 18 | "posttest": "yarn lint" 19 | }, 20 | "files": [ 21 | "index.js", 22 | "lib" 23 | ], 24 | "publishConfig": { 25 | "access": "public" 26 | }, 27 | "devDependencies": { 28 | "c8": "10.1.3", 29 | "got": "9.6.0", 30 | "mocha": "10.7.3", 31 | "sinon": "18.0.0" 32 | }, 33 | "dependencies": { 34 | "p-wait-for": "3.2.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/webhook-mock-receiver/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/zip/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/node' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/zip/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Ghost Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/zip/README.md: -------------------------------------------------------------------------------- 1 | # Zip 2 | 3 | ## Install 4 | 5 | `npm install @tryghost/zip --save` 6 | 7 | or 8 | 9 | `yarn add @tryghost/zip` 10 | 11 | 12 | ## Usage 13 | 14 | ``` 15 | const zip = require('@tryghost/zip'); 16 | 17 | // Create a zip from a folder 18 | 19 | let res = await zip.compress('path/to/a/folder', 'path/to/archive.zip', [options]) 20 | 21 | // Extract a zip to a folder 22 | 23 | let res = await zip.extract('path/to/archive.zip', 'path/to/files', [options]) 24 | ``` 25 | 26 | ## Develop 27 | 28 | This is a mono repository, managed with [lerna](https://lernajs.io/). 29 | 30 | Follow the instructions for the top-level repo. 31 | 1. `git clone` this repo & `cd` into it as usual 32 | 2. Run `yarn` to install top-level dependencies. 33 | 34 | 35 | ## Run 36 | 37 | - `yarn dev` 38 | 39 | 40 | ## Test 41 | 42 | - `yarn lint` run just eslint 43 | - `yarn test` run lint and tests 44 | 45 | 46 | 47 | 48 | # Copyright & License 49 | 50 | Copyright (c) 2013-2025 Ghost Foundation - Released under the [MIT license](LICENSE). 51 | -------------------------------------------------------------------------------- /packages/zip/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extract: require('./lib/extract'), 3 | compress: require('./lib/compress') 4 | }; 5 | -------------------------------------------------------------------------------- /packages/zip/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tryghost/zip", 3 | "version": "1.1.49", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/TryGhost/framework.git", 7 | "directory": "packages/zip" 8 | }, 9 | "author": "Ghost Foundation", 10 | "license": "MIT", 11 | "main": "index.js", 12 | "scripts": { 13 | "dev": "echo \"Implement me!\"", 14 | "test": "NODE_ENV=testing c8 --all --reporter text --reporter cobertura mocha './test/**/*.test.js'", 15 | "lint": "eslint . --ext .js --cache", 16 | "posttest": "yarn lint" 17 | }, 18 | "files": [ 19 | "index.js", 20 | "lib" 21 | ], 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "devDependencies": { 26 | "c8": "10.1.3", 27 | "folder-hash": "4.0.4", 28 | "fs-extra": "11.2.0", 29 | "mocha": "10.7.3", 30 | "should": "13.2.3", 31 | "sinon": "18.0.0" 32 | }, 33 | "dependencies": { 34 | "@tryghost/errors": "^1.3.8", 35 | "archiver": "^5.0.0", 36 | "extract-zip": "^2.0.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/zip/test/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['ghost'], 3 | extends: [ 4 | 'plugin:ghost/test' 5 | ] 6 | }; 7 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/.well-known/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/zip/test/fixtures/test-theme/.well-known/.gitkeep -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/.well-known/hello.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/zip/test/fixtures/test-theme/.well-known/hello.txt -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/assets/screenshot-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/zip/test/fixtures/test-theme/assets/screenshot-desktop.jpg -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/assets/screenshot-mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TryGhost/framework/e5272e66f281672e9e1072b16d8a198dc9ce14fb/packages/zip/test/fixtures/test-theme/assets/screenshot-mobile.jpg -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/locales/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Top left Button": "Oben Links." 3 | } 4 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "Top left Button": "Left Button on Top" 3 | } 4 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/byline-single.hbs: -------------------------------------------------------------------------------- 1 | {{!-- Everything inside the #author tags pulls data from the author --}} 2 | {{#primary_author}} 3 | 4 |
5 | {{#if profile_image}} 6 | {{name}} 7 | {{else}} 8 | {{> "icons/avatar"}} 9 | {{/if}} 10 |
11 |

{{name}}

12 | {{#if bio}} 13 |

{{bio}}

14 | {{else}} 15 |

Read more posts by this author.

16 | {{/if}} 17 |
18 |
19 |
20 | Read More 21 |
22 | 23 | {{/primary_author}} 24 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/avatar.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/facebook.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/infinity.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/location.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/point.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/rss.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/twitter.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/fixtures/test-theme/partials/icons/website.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/zip/test/utils/assertions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Should Assertions 3 | * 4 | * Add any custom assertions to this file. 5 | */ 6 | 7 | // Example Assertion 8 | // should.Assertion.add('ExampleAssertion', function () { 9 | // this.params = {operator: 'to be a valid Example Assertion'}; 10 | // this.obj.should.be.an.Object; 11 | // }); 12 | -------------------------------------------------------------------------------- /packages/zip/test/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Utilities 3 | * 4 | * Shared utils for writing tests 5 | */ 6 | 7 | // Require overrides - these add globals for tests 8 | require('./overrides'); 9 | 10 | // Require assertions - adds custom should assertions 11 | require('./assertions'); 12 | -------------------------------------------------------------------------------- /packages/zip/test/utils/overrides.js: -------------------------------------------------------------------------------- 1 | // This file is required before any test is run 2 | 3 | // Taken from the should wiki, this is how to make should global 4 | // Should is a global in our eslint test config 5 | global.should = require('should').noConflict(); 6 | should.extend(); 7 | 8 | // Sinon is a simple case 9 | // Sinon is a global in our eslint test config 10 | global.sinon = require('sinon'); 11 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@tryghost:quietJS" 4 | ], 5 | "ignoreDeps": [ 6 | "@elastic/elasticsearch", 7 | "moment-timezone", 8 | "validator" 9 | ] 10 | } 11 | --------------------------------------------------------------------------------