refs https://github.com/TryGhost/Team/issues/1249
This contains the initial frontend code to provide a working slider for
the Before/After card. The JS is enclosed in an IIFE so as to not leak
any variables, and the CSS is all scoped to the card only to avoid
interfering with existing styles.
refs https://github.com/TryGhost/Team/issues/1229
- bumped @tryghost/kg-default-cards that contains initial video card rendering
- added video card CSS file with basic style that prevents video element rendering larger than the content width (similar to default image styles in most themes)
no issue
- wraps the card js scripts into an IIFE to avoid polluting global variables on the site
- also any fixes errors caused by `swup` and its scripts-plugin that trips over already created global variables
no-issue
Using the async attribute means that the script is downloaded in
parallel with the parsing of the html into DOM, and then executed upon
completion. This means that the script cannot be sure that particular
parts of the DOM exist as it may not have finished parsing. This has
resulted in bugs with the new toggle card not working.
Switching our script to use the defer attribute means that the script is
still downloaded in parallel with parsing, but it is not executed until
parsing is complete. This means that the script can safely access the
DOM.
refs https://github.com/TryGhost/Team/issues/1001
This adds custom rendering to Twitter embeds for email newsletters, so
that rather than displaying a plaintext blockquote with the tweet
contents, we render an rich Twitter card.
refs: https://github.com/TryGhost/Toolbox/issues/146
Switched to @tryghost/logging instead of passing around the library. The main sticking points of this change are jobs. When jobs are launched we don't want them to use a separate @tryghost/logging instance because they would start parallel rotation jobs. @tryghost/logging v2.x passes all logs to the parent process if run in a child process, so that we can use the same patterns in jobs and the rest of the codebase.
refs https://github.com/TryGhost/Team/issues/1206
- The callout card displays an emoji and a paragraph of text inside a highlighted box.
Co-authored-by:
- Sanne de Vries (@sanne-san)
refs https://github.com/TryGhost/Toolbox/issues/152
- Because the root app module was initialized only once per runtime it caused all the express apps to stack on each other causing all sorts of strange behavior when trying to test redirects/vhost mounts etc. Lesson here: be very cautious of how the module is initialized, an explicit function is almost always a better way!
refs 3c7a8dead4
- The idea is a rip-off from the referenced commit. It allows to isolate initialization logic to "frontend" mounted on top of a "parent"
- Gives path to simplify the express-mock tests
Co-authored-by: Hannah Wolfe <erisds@gmail.com>
refs https://github.com/TryGhost/Toolbox/issues/152
- This stops the mounting of the admin and frontend from being buried deep in express initialisation
- Instead it's explicit, which makes two things almost possible:
1. we can potentially boot the frontend or backend independently
2. we can pass services and settings loaded during boot into the frontend
- This needs more work, but we can start to group all the frontend code together
- Meanwhile we also need to rip apart the routing and url services to decouple the frontend from the backend fully
- BABY STEPS!
Co-authored-by: Hannah Wolfe <erisds@gmail.com>
refs https://github.com/TryGhost/Ghost/issues/13837
- a [refactor](9fa8800b9d) in `@tryghost/bootstrap-socket` changed the signature of the method it exprots, but the use of this
library wasn't updated in Ghost
- therefore, the library was trying to send the `@tryghost/logging` library, which caused
errors with Ghost-CLI down the line, as mentioned in the issue
- this commit updates the method signature to match what is expected
no-issue
Some NFT's are created without a title, for example the Bored Ape Yacht
Club collection does not name the tokens, instead just referring to them
by ID. This change falls back to the token_id, which is unqiue within
the collection to support these tokens.
refs https://github.com/TryGhost/Team/issues/960
- Character like "%%" or "%80" would crash our current url escaping behavior. We consider they aren't valid URLs as the percentages haven't been properly escaped.
refs https://github.com/TryGhost/Team/issues/1200
- The error was fixed in a1421c2380
- The error catching prevents future 500 errors in the API
- The logging enable visibility on these errors to fix them if they happen
refs https://github.com/TryGhost/Team/issues/1200
- The leading/trailing whitespaces are trimmed by `new URL()` but are considered invalid in metascraper. Trimming solves this edge case.
refs https://github.com/TryGhost/Toolbox/issues/151
refs cbec6aa49e
- Without the await the try/catch block does not catch a pottential validation error straight away, which leads to a 500 error instead of a validation error being returned. The regression was introduced during the refactor (part of referenced commit).
This reverts commit 303ea87897.
- Although gscan catches these now, we have a number of sites that have slipped through the net
- Reverting until we get them all cleaned up
- one big file full of stuff is never good for clarity
- separating it out helps us see what requires what
- it also highlights the awful naming and opaque behaviour we have in themes - much to do, but this helps us start
refs https://github.com/TryGhost/Toolbox/issues/151
refs cbec6aa49e
- The error was happening due to incorrect "this" context. Because the filename and extension are only used once in this class and only for the purposes of the error message have moved the whole thing into the error message itself. No need to keep additional variables around when there's no clear usecase.
refs https://github.com/TryGhost/Team/issues/1067
As part of the work of automatically logging members in after payment,
we want to revisit the emails. Currently after payment we send an email
asking a member to _confirm_ their subscription, and that they can
ignore the email to cancel the subscription. This is not the case
however, as the member has already been subscribed.
refs: TryGhost/Toolbox#147
* Replaces all references to isIgnitionError with isGhostError
* Switches use of GhostError to InternalServerError - as GhostError is no longer public
There are places where InternalServerError is not the valid error, and new errors should be added to the @tryghost/errors package to ensure that we can use semantically correct errors in those cases.
refs https://github.com/TryGhost/Team/issues/1234
Sharp can occasionally fail resizing, this is usually due the the
underlying libvips library failing. We do not want this to cause an
error however, instead we should just show the original image - as
resizing is an optimisation, rather than a requirement.
refs https://github.com/TryGhost/Team/issues/1001
We fall back to existing behaviour if no API key is present, or if there
is an error communicating with the Twitter API. We're also currently
requesting all the data, which will be thinned down once we understand
what we need.
This also includes a custom renderer for embeds of type "twitter" which
will be used to output the custom HTML for emails
- our themeErrorRenderer is only used in the frontend.. move it there
- this required exposing prepareError as shared middleware
- TODO: move these shared compontents to @tryghost/error
refs: 0799f02e80
refs: 5e931e2e37
- with the referenced two commits I replaced our old HTML renderer with some code borrowed heavily from finalHandler
- I had intended to modify this further to out put our message, context and help error messages
- However, I ended up doing this in prepareError so it's done for all error renderers
- There's now very little point keeping duplicated code from finalHandler just to output the status code
- If we remove this code, express will fall back to finalHandler anyway, so the output is near identical
- got rid of old _private & variable pattern in favour of const and module.exports
- changed weird capitalisation naming conventions to be camelCase
- removed some very old TODOs that we're never gonna get TODONE
- these are mostly old ideas that never made it, and it's been so long they're clearly not important
refs: https://github.com/TryGhost/Toolbox/issues/105
Lint rules prevent:
* Invalid naming conventions for new migrations
* Loop constructs in migrations - these should be used with caution
and are therefore a warning rule, use `// eslint-disable-next-line
no-restricted-syntax` to prevent this rule from firing where a loop is
required
* Returing within a loop - this is usually meant to be a
continue/break
* Multiple joins - these can be badly performing migrations, so should
be treated with caution, disable the rule for the line if the risk is
understood / the migration cannot be written without it
refs: 4474ca1a1d
refs: 0799f02e80
The BasicErrorRenderer was created as a fallback for when we needed to not render templates, which is
chiefly when we're trying to render a 404 for an image. Using a template puts us at risk of an infinite 404 loop
if the missing image is referenced in the 404 template.
As of 0799f02e, the HTMLErrorRenderer no longer uses templates - instead we serve a very simple HTML page.
This can be used instead of the BasicErrorRenderer, as it results in a properly formatted error.
Even when sending responses in plain text, the content type is returned as HTML and therefore having an
unformatted error makes no sense - if we really need a non-html format I guess there should be no body at all.
refs https://github.com/TryGhost/Toolbox/issues/120
- Having an "options" parameter in the controller definition was missleading as if the `url` or `ref` parameters were expected as a part of the qurey parameter. These variables should be provided as a part of the request body, thus having them in "data" attribute is more accurate
refs https://github.com/TryGhost/Toolbox/issues/139
- Having tight coupling with backup file path calculation for redirects makes it extremely hard to test. In addition, having it injected will make it easier to swap this dependency to the mechanism similar to one used for routes files
refs https://github.com/TryGhost/Toolbox/issues/139
- The custom redirects services belong in the initServicesForFrontend because frontend depends on these to function properly. When placed in general init section the middleware would not get initialized properly before it's used by the "frontend express app"
refs https://github.com/TryGhost/Toolbox/issues/139
- The pattern we use accross the codebase is a single "options" object passed into a constructor instead of passing multiple parametes. Fixed the broken pattern in CustomRedirectsAPI constructor
refs 91efa4605c
- Referenced commit introduced a double json-stringification to uploaded redirects.json files.
- The endpoint has no stability index of any sort and is meant to be dropped in Ghost v5. It's best to rework the redirects to the yaml format as descirbe here - https://ghost.org/docs/tutorials/implementing-redirects/#file-structure
- moving this middleware because we're about to add a second piece of middleware
- it's easier to see what we have when each middleware is in its own file rather than in one big middleware.js file
refs https://github.com/TryGhost/Team/issues/1236
We use Offer names for the Stripe Coupon name - which has a limit of 40
characters. We are now introducing a limit of 40 characters to Offer
names too. This migration ensures that all our data in the DB is valid.
no issue
When switching the oembed service to async/await the error handling was not correctly refactored. `this.errorHandler(url)` was returning a curried function so it could be used as `.catch(this.errorHandler(url))` but that's not how it's being used after the async/await change meaning we were returning a function rather than the result of that function.
- `this.errorHandler(url)` is now only used in one place where `url` is available so removed the method and moved the body of the curried function inline into the `catch` handler
- added a message to the logged error so it's more clear what the log refers to
refs https://github.com/TryGhost/Team/issues/1236
We use Offer names for the Stripe Coupon name - which has a limit of 40
characters. We are now introducing a limit of 40 characters to Offer
names too. This migration ensures that all our data in the DB is valid.
- When we handle errors in Ghost, we are supposed to use a pattern of supplying 3 messages:
- message: what went wrong
- context: details about why how or where the error happened
- help: where the user can go to get help with this error
- We do this in many places and our JSON error handler and CLI error logging tools are designed to output this extra information
- However, stack traces, which start with message as the first line and then output the stack are totally missing this
- By injecting the additional messages into the stack once an error has been "ghostified" we should get clearer messages everywhere
Notes:
- I've additionally injected a "Stack Trace:" line that makes it easier to read the error vs the stack
- This code looks a little weird because the lines are inserted backwards, but that allows us to always to the insert at position 1 as per the comment,
so we don't have to keep track of whether we already injected something or not
refs: 2af9e2e12
- This new HTMLErrorRenderer is borrowed heavily from finalHandler
- This is the module that express uses to render errors if there is no custom errorhandler
- It just renders a really simple html page wrapping err.stack in a <pre>
- This results in a nicely formatted, but unstyled error page
- I also updated BasicErrorRenderer to use the same res.statusCode + err.stack pattern rather than err.message
Note: This error renderer is _only_ used for renderering errors on the `/ghost/` route
- In almost all cases, errors here are rendered by Ember
- The only error that can be rendered here is a missing template error see: 2af9e2e12
- If the admin templates default.html or default-prod.html are missing, don't throw a 500
- Instead throw a well considered 400 error with extra help for what to do to fix it
- Reduced our maintenance middleware code down to the bare minimum!
- We have an old maintenance middleware in place to handle when a site is forcibly put into maintenance mode, or the urlService hasn't finished booting
- This maintenance middleware was mounted on every sub app, instead of globally for reasons I no longer remember
- Recently, we introduced a new, static version of maintenence middleware to show during the boot process so we can get the server started earlier & not drop requests
- This version has its own HTML template and doesn't depend on any of Ghost's error rendering code
- To simplify and help with decoupling, this commit merges the two middleware, so that the new independent & static middleware renders its template for any one of the 3 possible maintenance modes
- It only needs to exist in the top level app 🙌
TODO: move the maintenance middleware to its own file/package so it's not part of the app.js as that is weird
- throughout the theme activation flow there are several missing awaits and necessary async keywords
- we should be waiting on these processes, not letting them complete indeterministically
refs bb47b9e327
- EACCESS error was previously caught to stop the boot process from failing with perms errors
- For clearFiless, we do not care if these files cannot be removed. Refactored to use allSettled which means we don't do them in sequence + can ignore the outcome
- For minifiy, this is now a legit error, however we don't need the activate method to fail for an EACCES error, we just need an error to be shown (I think)
refs https://linear.app/tryghost/issue/CORE-35/refactor-route-and-redirect-settings
- It's a step to making the module follow class+DI pattern before fully extracting it into an external libarary
- Reminder, doing in Ghost repo instead of substituting big chunks all at once to have clear history of how the service evolved prior to the extraction into external lib!
- Card asset reloading was incorrectly only happening if the API version changed 🙈
- In addition, having an init function was redundant, as theme activation happens on boot
- This meant that the card assets were being generated twice on boot
- Instead, we now only generate them on theme activation, which covers the boot case and simplifies all the logic
- Currently it's assumed that public files are 100% static
- With card assets, we're using it for files that are partially static, but can change between reboots and theme changes
- We already have a system for managing cache busting across theme changes and restarts - the ?v= key that is added via the asset helper
- This was already in place and used, but servePublicFile's internal cache didn't honor this key, and cached for the lifetime of boot
- This small change means that if a ?v= query param is present on a request for a public file, that we pay attention to it. Else we cache as before
no issue
When switching the oembed service to async/await the error handling was not correctly refactored. `this.errorHandler(url)` was returning a curried function so it could be used as `.catch(this.errorHandler(url))` but that's not how it's being used after the async/await change meaning we were returning a function rather than the result of that function.
- `this.errorHandler(url)` is now only used in one place where `url` is available so removed the method and moved the body of the curried function inline into the `catch` handler
- added a message to the logged error so it's more clear what the log refers to
refs https://github.com/TryGhost/Toolbox/issues/135
- Looking closer into the reason why the test was failing without "forceStart" revealed that the server only start was overoptimized - "initServicesForFrontend" should be a part of a backend as those are generic theme services.
refs https://github.com/TryGhost/Toolbox/issues/135
- The reason the test **settings** test was failing when the force start flag was removed in the **custom themes** was the bridge! The bridge was trying to execute function on the frontend when the boot was done without initializing the frontend. The setting test was changing locale and the timezone which triggered events calling up on frontend components - we clearly don't want to do this when the instance is booted without the frontend
- To make event initialization conditional moved it to the "init". This way the event listeners are only set up when we boot with the "frontend" flag set to true
refs https://github.com/TryGhost/Toolbox/issues/135
- Without sensible defaults the web app was not initializing either the backend nor the frontned parts of the application. Fixed the defaults so the problem doesn't happen again and optimized mock-express-style initialization to only initialize the frontend routing
no issue
- `startsWith` method is way easier to read and understand. also, **probably** has better performance comparing to building up a regexp and then matching
refs https://github.com/TryGhost/Toolbox/issues/135
- When instantiating new Urls/Resources object in the UrlService's init on every test suite start it was loosing track of past events (softReset wasn't doing the cleanup properly). Not initializing new classes "fixes" the problem partially, by not loosing track of those event listeners. The real fix should be proper even listener cleanup on every soft reset!
refs https://github.com/TryGhost/Toolbox/issues/135
- Allows to turn off overwriting urls/resources JSON file caches on testing environment. This is needed to have predictable state when running multiple test suites that stop the Ghost process and try to persiste URL cache.
refs https://github.com/TryGhost/Toolbox/issues/135
- This extracts the file storage knowledge out of the URL Service an allows to have optional features based on the environment - for example turning off writing cache for when running tests
refs https://github.com/TryGhost/Toolbox/issues/135
- To be able to reliably start ghost instance without a frontend the process needs access to urls/resources caches
- Storing the configuration in "paths" for now as there's no better place for it untill we are able to mock the content folder in pre-boot
refs https://github.com/TryGhost/Toolbox/issues/135
- These flags are meant to control initialization of sections of the boot sequence depending on the needs - with or without bakend (API)/frontend (public handlebars site)
- Ideally these flags should not be passed deep into the components, and if the are (like in the web/parent/app case) it's a smell that we need to move things up into the boot process!
closes: https://github.com/TryGhost/Ghost/issues/13739
- Ghost cannot write to the core folder in correctly configured production installations
- Built assets therefore need to be written to the content directory
- Ghost does not overwrite anything in the content folder as part of an upgrade, therefore static files that are provided by Ghost
must still live inside /core
- So as a result, we now have core/frontend/public and content/public
- These two things are meant to improve performance at the cost of reliability.
- Perfect for testing, however I think they make a minimal impact on modern SSDs :(
- Still worth a shot to see if it helps with CI
refs https://github.com/TryGhost/Toolbox/issues/136
- `cheerio` isn't needed during the boot but it takes time and memory to
load the library
- this commit moves `cheerio` requires later into the code to when they
are needed
no issue
- if we encounter an unexpected error whilst fetching embed details we return a generic validation error so we're not leaking any details about the URL that is being hit, however that meant the error logs were only showing validation errors making debugging difficult
- added explicit logging of the unexpected error before throwing the generic validation error
- These are simple functions that get data from config in a specific format
- They are also used by the topmost part of the application
- Config helpers seems like a reasonable fit to get them out of the web folder
- Functions have also been renamed to try to get them to make more sense
refs https://github.com/TryGhost/Team/issues/1211
Added ?format=json to the URL in an attempt to mitigate any issues with
weird caching and receiving HTML rather than JSON.
Used `type` in place of `card_type` to closer follow how the bookmark
card/embed works.
Removed the html & width/heihgt properties which are not needed at all.
refs https://github.com/TryGhost/Team/issues/1217
- moved top-level `tenorApiKey` to `tenor:apiKey` and added `tenor:contentFilter`
- added base config to `defaults.json`
- updated `public-config.js` and API output serializer to use the new top-level `tenor` key
https://github.com/TryGhost/Toolbox/issues/130
The transaction no longer commits in the promise chain, which wasn't
valid logic for a transaction, since it is commited automatically when
the promise chain resolves, and rollsback automatically when the
promise chain rejects.
This makes code which fails during the transaction error in the right
place, instead of getting stuck here. (Especially good for writing
tests).
The tests for this code can now live in the integration folder.
- This is a minor bugbare, but it will affect some configuration I'm about to do for c8
- I've been wanting to do it for ages, middleware is plural all on it's own so it's an odd affectation in our codebase
- This also only exists in 2 places, everywhere else we use "middleware"
- Sadly it did result in a lot of churn as I did a full find and replace, but consistency is king!
- The version util is now required in logging as well as sentry and migrations
- I can see us needing it in config too, so put it straight to the first item
- we do this so that the debug statements can tell us how long each step took as we look to optimise everything
- this keeps production and test fixtures separate, so that changing the prod fixtures doesn't change the shape of our tests.
- we may still want to test that the production fixtures do what we expect, but that can be handled in a separate integration test, by specifically setting the fixture path
refs: https://github.com/TryGhost/Toolbox/issues/133
- instead of just a collection of utils, we now have a class that manages fixtures
- this should allow us to change the path to fixtures, e.g. between prod/dev and test, so that different fixtures can be loaded by default
- also makes it easier to test the fixture manager code itself
refs https://github.com/TryGhost/Toolbox/issues/127
- New instances or Urls and Resources during init were messing up test suites without an obvious solution. Moved them to only be triggered when the cache is present.
- Note the e2e-frontend tests are failing if thie initialization happens every time when init is called. There seems to be some reliance on Resources being the same intsance between "softReset" which seems wrong, but wasn't able to track it down definitevely
refs https://github.com/TryGhost/Toolbox/issues/127
- The resource cache is needed to have quick and reproducible state of the resouces tied to the urls instead of waiting for the db queries to finish.
- Allows to use UrlService without any database connection at all - useful for unit testing
- At the moment there's no way to see in the logs when the URL Service finally finishes
- This is the moment when Ghost stops serving 503s
- Adding this log line so it's clear to see, which migh be useful whilst were refactorising
refs https://github.com/TryGhost/Toolbox/issues/127
- The "withUrlOptions" is used internally in the constructor by the frontend's routers. To avoid passing around a whole function from the frontend routers duplicated the functionality from there.
refs 5a62253466
- The UrlService was relying on a "hidden" identifier field that was passed along with a router object. Now it's passed as an explicit parameter from the "frontend" to the backend's UrlService
refs https://github.com/TryGhost/Toolbox/issues/127
- Passing around whole instance of a frontend router was an overkill when there are only 3 static pieces of information that needed to be loaded. Extracting the router out makes the UrlGenerator way more readable, tests slimer, and the memory footpring of the process should be slightly lighter
- The toString overloading didn't make sense at the time of this refactor, maybe if there's a concrete usecase we could resurect it in a form of passing in a router's name or something.
refs https://github.com/TryGhost/Toolbox/issues/127
- This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes
- This is almost the last piece to free us up from the massive "router" object that has been passed around
refs https://github.com/TryGhost/Toolbox/issues/127
- This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes
refs https://github.com/TryGhost/Toolbox/issues/127
- This is an effor t to define a precise set of data needed for the UrlGenerator to function, which should help with decoupling it from the frontend routes
refs: https://github.com/TryGhost/Ghost/issues/13739
- This is a short term fix to prevent this new feature causing boot errors
- This will allow development to continue uninterrupted this week & also allow us to do a rollout
- The proper fix will be to move where these files live, which will be done before we go live
refs https://github.com/TryGhost/Team/issues/1211
Instead of rendering the HTML as an embed - we will send back the
necessary data. This will allow us to keep all the knowledge of HTML
structure in the Koenig repository.
refs https://github.com/TryGhost/Toolbox/issues/125
- The in-memory url objects would be persisted in the contents folder allowing to take advantage of the cache during the next instance start
refs https://github.com/TryGhost/Toolbox/issues/125
- The url loader is not fully working and is in very experimental mode. The aim is to ship this version to allow other team members to play with the feature in limited use-cases like testing evnironment
refs https://github.com/TryGhost/Toolbox/issues/116
- This should allow testing in a bit easier manner and would place the file into a more suitable directory
- ideally we'd put an alfa flag bahind this new "cached routes" feature to have less consequences to deal with if we have to back out
refs https://github.com/TryGhost/Toolbox/issues/116
- This is a PoC to check out how viable this approach is and if it's worth merging into main as a very quick win
- The `urls.json` is in a bad place right now should probably live in a data folder
refs https://github.com/TryGhost/Toolbox/issues/125
- Config initialization for the URL Resouces is a separate stage which doesn't have to be bundled along with resouce fetching method
- It gives even more flexibility when composing different ways to get the "resources" loaded into memory: right now it's from the DB but could come from a cache
refs https://github.com/TryGhost/Toolbox/issues/125
- The "init" method pattern is not used across the codebase and it's pretty standard to start the service in this way. Previous description was outdated and misguiding
refs https://github.com/TryGhost/Toolbox/issues/125
- The "fetchResources" method did way to many things extracted event listener setup logic to a separate method
- This allows to call out these stages as needed if we retreive resources separately from a cache of some sort and don't need to wait for the database response
refs https://github.com/TryGhost/Toolbox/issues/125
- The "fetchResources" is only used from one place and does way to many things at once:
- Fetches resources from the DB-
- Hooks up event listeners
- Starts the queue
- These are three different things, and should be three different methods ideally
refs https://github.com/TryGhost/Team/issues/1217
- add `tenorApiKey` to `publicConfig.config()
- update canary config endpoint output serializer to include `tenorApiKey` when the `gifsCard` labs flag is enabled
refs https://github.com/TryGhost/Team/issues/1211
This registers the NFT custom OEmbed provider to the OEmbed service for
the canary API. This should probably be done in a centralised place -
but we do not have a single instance of the OEmbed service.
When we have more information about why the OEmbed service is
instantiated like this, we can think about moving it into a singleton
service with an `init` method - which is where we can register custom
providers.
refs https://github.com/TryGhost/Team/issues/1211
This adds the initial custom OEmbed provider for OpenSea NFT's - we're
using the new custom provider functionality so that we can easily change
the logic here without affecting the core functionality.
refs https://github.com/TryGhost/Team/issues/1211
In order to override the default OEmbeds for OpenSea NFT's we need a way
to provide out own OEmbed data. We will want this in future too for
custom Twitter embeds, so this has been built in a way which allows
extension.