no issue
- i18n is deprecated in favour of `tpl`
- normalized method syntax so `add` matches the rest of the controller's methods (fixed a complexity warning but was not the primary intention)
- This isn't really a "service" - it's a set of utilities for working with labs flags
- It's also required all over the place, and doesn't require anything that isn't shared
- Therefore, it should live in shared
- This isn't really a "service" - it's a set of utilities for working with labs flags
- It's also required all over the place, and doesn't require anything that isn't shared
- Therefore, it should live in shared
- This is part of the quest to separate the frontend and server & get rid of all the places where there are cross-requires
- At the moment the settings cache is one big shared cache used by the frontend and server liberally
- This change doesn't really solve the fundamental problems, as we still depend on events, and requires from inside frontend
- However it allows us to control the misuse slightly better by getting rid of restricted requires and turning on that eslint ruleset
- We were using the same bind pattern for both internal-only and public helpers
- Binding helpers to config makes them available throughout the codebase
- Removing the binding doesn't make the code much more complicated, but it does make the Public API of the config module a lot clearer
- The new @tryghost/config-url-helpers has a pattern of exposing bindAll()
- Changed the local (non url) helpers to have the same pattern for consistency
- Also fixed types as best I can
- getSubdir, getSiteUrl & getAdminUrl were currently part of @tryghost/url-utils
- They have been split out into their own library, and refactored so that they expect to be bound to nconf
- With this commit we can do e.g. config.getSubdir() rather than needing @tryghost/url-utils
- These functions will be passed to url-utils via DI
- This is the first step in breaking down url-utils into smaller pieces
- This commit only does a single change in Gruntfile.js to use the new funtions - this will be rolled out slowly
no issue
Fixes commit caea330647 when running on Ghost (Pro), this is a temporary patch that will be removed when there are no references to the logging module.
- There are two different types of function here
1. "helpers" are public API - config.something() that provide dynamic helpers on top of config
2. "utils" are internal methods used only by config itself
- This commit makes this distinction clearer, although we should also change the code to enforce that utils are not exposed
- Renamed the file in line with our rules around index.js files
- Cleaned up some outdated code patterns
- Want to make the config module a little clearer in what it does
no issue
The only pieces of Ghost-Ignition used in Ghost were debug and
logging. Both of these modules have been superceded by the Framework
monorepo, and all usages of Ignition have now been removed, replaced
with @tryghost/debug and @tryghost/logging.
refs https://github.com/TryGhost/Team/issues/767
- adds new multiple products UI in Portal (works behind the `multipleProducts` feature flag)
- Portal's current single product UI behaves the same when flag is switched off
- We are going to get rid of the internal i18n tool because it doesn't solve a real use case
- Instead, we have a new tpl utility that does basic string interpolation
- This pattern will make it easier for us to decouple the codebase, and the new tool helps to keep the refactor surface area really small
- This is the first example of using the new tpl helper, so it also adds @tryghost/tpl
refs https://github.com/TryGhost/Team/issues/718
This bumps Portal to `~1.5.1` which handles changes for multiple tiers/products -
- Handles updated `portal_plans` setting to use monthly/yearly again
- Handles list of available prices to use prices across multiple products
no refs
As part of new membership settings in Admin, we need to resize the Portal preview container to dynamically adjust to selected preview options. Portal is updated to handle and fire resize events for Admin on popup container changes so the preview can be adjusted correctly.
- Bumps minimal Portal version to ~1.4.6
no issue
Our server-defined `mobiledoc` object was required by `UrlUtils.cardTransformers` property to help set up a shortcut for url transform functions but that was breaking the independence of `UrlUtils` by crossing the shared/server boundary.
- `cardTransformers` is only needed for the `mobiledocToTransformReady` utility function that will only be used by the server
- removed `UrlUtils.cardTransformers` (and associated require) from our `UrlUtils` instance and updated the few areas the server uses `mobiledocToTransformReady()` to pass in the mobiledoc card objects directly as an option
refs https://github.com/TryGhost/Team/issues/560
refs 196cdafe6b
The endpoint `/members/api/member/` used by Portal for fetching member details was updated to return 204 No Content instead of 401. This change updates Portal to handle updated API response for logged out member, along with couple of bug patches -
- 🐛 Fixed extra email sent for logged in members on upgrade
- 🐛 Fixed falsy value not used in preview
commit 9c498697c9
issue https://github.com/TryGhost/Team/issues/694
`process.env.npm_package_version` is only filled when Ghost is started via npm scripts, so it would have been empty when starting Ghost using `node index.js`
refs https://github.com/TryGhost/Team/issues/581
closes https://github.com/TryGhost/Team/issues/582
Emails can now be sent to members with specific associated labels or products by specifying an NQL string. We want to bring the same members segment feature to content by allowing `visibility` to be an NQL filter string on top of the `public/members/paid` special-case strings.
As an example it's possible to set `posts.visibility` to `label:vip` to make a post available only to those members with the `vip` label.
- removed enum validations for `visibility` so it now accepts any string or `null`
- bumped `@tryghost/admin-api-schema` for API-level validation changes
- added nql validation to API input validators by running the visibility query against the members model
- added transform of NQL to special-case visibility values when saving post model
- ensures there's a single way of representing "members" and "paid" where NQL gives multiple ways of representing the same segment
- useful for keeping theme-level checks such as `{{#has visibility="paid"}}` working as expected
- updated content-gating to parse nql from post's visibility and use it to query the currently logged in member to see if there's a match
- bumped @tryghost/members-api to include label and product data when loading member
refs https://github.com/TryGhost/Team/issues/581
refs https://github.com/TryGhost/Team/issues/582
When publishing a post via the API it was possible to send it using `?email_recipient_filter=all/free/paid` which allowed you to send to members only based on their payment status which is quite limiting for some sites.
This PR updates the `?email_recipient_filter` query param to support Ghost's `?filter` param syntax which enables more specific recipient lists, eg:
`?email_recipient_filter=status:free` = free members only
`?email_recipient_filter=status:paid` = paid members only
`?email_recipient_filter=label:vip` = members that have the `vip` label attached
`?email_recipient_filter=status:paid,label:vip` = paid members and members that have the `vip` label attached
The older `free/paid` values are still supported by the API for backwards compatibility.
- updates `Post` and `Email` models to transform legacy `free` and `paid` values to their NQL equivalents on read/write
- lets us not worry about supporting legacy values elsewhere in the code
- cleanup migration to transform all rows slated for 5.0
- removes schema and API `isIn` validations for recipient filters so allow free-form filters
- updates posts API input serializers to transform `free` and `paid` values in the `?email_recipient_filter` param to their NQL equivalents for backwards compatibility
- updates Post API controllers `edit` methods to run a query using the supplied filter to verify that it's valid
- updates `mega` service to use the filter directly when selecting recipients
- we need the basePath concept for the main i18n class so we can pull it out into a module
- we already had this in the themeI18n class, so I just had to move it up
- also I added a default of __dirname, so we don't have to declare this constantly in the tests
- Reworking the location of i18n in boot has fixed the main error
- However, many of our tests depend on i18n being loaded but don't explicitly call init
- There are many ways we could fix this in our tests, but I don't want to spend more time on this now
- final preparation for moving i18n out of Ghost core
- logging is passed in via DI
- theme i18n needs a config value, but no need to pass all of config for one parameter, a better pattern is to pass the one value needed
- preparation for moving the base class out of Ghost
- refactored so that all the logic for file loading and fallbacks live in the base class
- theme i18n now only overrides init with the properties it needs, filepath generation and error handling
- this makes it much easier to move the i18n file out, and eventually have theme i18n live elsewhere too
- also prepares for using DI for logging
- calling i18n as a global const like this requires it to be loaded before anything else, when we have to manage this with the init() flow
- wrapping it inside the function where it's used ensures we don't call i18n til we need it
- also improved the i18n called without init error to include the key it was called with
- Note: added a forced error to show that this was previously happening at the wrong time
- i18n is required by ghost-server to log server start messages, and so gets initialised as part of the ghost-server load
- moving this into the right place means we can see how long it takes in the debug logs
- previously the debug log lines for i18n showed 0/1ms, which is not correct as this contains a sync file load operation!
- we should consider if we want to have i18n be a requirement for ghost server, or if we want static messages
- the core i18n library and theme i18n library have slightly different methods of getting a candidate string
- both of them use forms of jsonpath, meaning they both require jsonpath as a dependency
- to try to get to a point of being able to rip more things out of ghost, we want to have less dependencies
- so instead of overloading the method, we pass in a stringMode as an argument
- eventually we might not need an overloaded class for themeI18n at all, which would simplify the codebase
- preparation for using DI instead of requires, so we can move this out of Ghost
- have done this for both the main i18n and theme i18n file
- refactored the constructor
refs 829e8ed010
- i18n is used everywhere but only requires shared or external packages, therefore it's a good candidate for living in shared
- this reduces invalid requires across frontend and server, and lets us use it everywhere until we come up with a better option
refs https://github.com/TryGhost/Team/issues/579
Updates minimum Portal version to handle the new `members_signup_access` setting and explicitly handle the `invite` option to make Portal work in invite only mode if selected
- Modules in /shared are supposed to be standalone modules that can be required by the server or frontend
- As the server shouldn't require the frontend, and vice versa, shared modules should require neither
- Otherwise it just becomes a crutch for allowing cross-depenencies, and will create circular dependencies
The Bridge
- The bridge file is not meant to be a crutch sat allowing cross-dependencies, but rather a new component that manages the flow of data
- That data flows from the server/boot process TO the frontend, and should not flow in the other direction
- The management of that flow of data is necessarily hacky at the moment, but over time the architecture here should get clearer and better
- Still, for the time being it will need to handle requiring across components until that architecture matures
- Therefore, it should live in core root, not in core/shared