-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Deprecated models.init
pattern for initializing models
#22358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThe changes remove synchronous calls to initialize models from various parts of the application and its test suites. In the core boot, CLI, REPL, migration hooks, update-check routines, and the model index file, the explicit call to ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
63f3aac
to
cdc385c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (67)
ghost/core/core/boot.js
(0 hunks)ghost/core/core/cli/generate-data.js
(0 hunks)ghost/core/core/cli/repl.js
(0 hunks)ghost/core/core/server/data/migrations/hooks/init/before.js
(0 hunks)ghost/core/core/server/models/base/listeners.js
(4 hunks)ghost/core/core/server/models/index.js
(1 hunks)ghost/core/core/server/models/user.js
(1 hunks)ghost/core/core/server/services/update-check/run-update-check.js
(0 hunks)ghost/core/core/server/web/api/testmode/jobs/graceful-job.js
(0 hunks)ghost/core/test/integration/url_service.test.js
(0 hunks)ghost/core/test/regression/api/admin/schedules.test.js
(0 hunks)ghost/core/test/regression/models/model_settings.test.js
(0 hunks)ghost/core/test/unit/api/cache-invalidation.test.js
(0 hunks)ghost/core/test/unit/api/canary/session.test.js
(0 hunks)ghost/core/test/unit/api/canary/utils/validators/input/pages.test.js
(0 hunks)ghost/core/test/unit/api/canary/utils/validators/input/posts.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/authors.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/get.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/ghost_head.test.js
(1 hunks)ghost/core/test/unit/frontend/helpers/recommendations.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/tags.test.js
(0 hunks)ghost/core/test/unit/frontend/meta/keywords.test.js
(0 hunks)ghost/core/test/unit/server/adapters/scheduling/post-scheduling/post-scheduler.test.js
(0 hunks)ghost/core/test/unit/server/data/db/backup.test.js
(0 hunks)ghost/core/test/unit/server/data/exporter/index.test.js
(0 hunks)ghost/core/test/unit/server/data/schema/fixtures/fixture-manager.test.js
(0 hunks)ghost/core/test/unit/server/data/schema/validator.test.js
(0 hunks)ghost/core/test/unit/server/models/api-key.test.js
(0 hunks)ghost/core/test/unit/server/models/base/crud.test.js
(0 hunks)ghost/core/test/unit/server/models/base/index.test.js
(0 hunks)ghost/core/test/unit/server/models/base/relations.test.js
(0 hunks)ghost/core/test/unit/server/models/comment.test.js
(0 hunks)ghost/core/test/unit/server/models/custom-theme-setting.test.js
(0 hunks)ghost/core/test/unit/server/models/integration.test.js
(0 hunks)ghost/core/test/unit/server/models/invite.test.js
(0 hunks)ghost/core/test/unit/server/models/member-click-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-created-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-feedback.test.js
(0 hunks)ghost/core/test/unit/server/models/member-paid-subscription-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-subscribe-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member.test.js
(0 hunks)ghost/core/test/unit/server/models/milestone.test.js
(0 hunks)ghost/core/test/unit/server/models/newsletter.test.js
(0 hunks)ghost/core/test/unit/server/models/permission.test.js
(0 hunks)ghost/core/test/unit/server/models/post.test.js
(0 hunks)ghost/core/test/unit/server/models/session.test.js
(0 hunks)ghost/core/test/unit/server/models/settings.test.js
(0 hunks)ghost/core/test/unit/server/models/single-use-token.test.js
(0 hunks)ghost/core/test/unit/server/models/stripe-customer-subscription.test.js
(0 hunks)ghost/core/test/unit/server/models/subscription-created-event.test.js
(0 hunks)ghost/core/test/unit/server/models/tag.test.js
(0 hunks)ghost/core/test/unit/server/models/user.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/api-key/admin.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/api-key/content.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/session/middleware.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/session/store.test.js
(0 hunks)ghost/core/test/unit/server/services/frontend-data-service/frontend-data-service.test.js
(0 hunks)ghost/core/test/unit/server/services/frontend-data-service/index.test.js
(0 hunks)ghost/core/test/unit/server/services/members/middleware.test.js
(1 hunks)ghost/core/test/unit/server/services/newsletters/index.test.js
(0 hunks)ghost/core/test/unit/server/services/newsletters/service.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/can-this.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/index.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/providers.test.js
(0 hunks)ghost/core/test/unit/server/services/staff/index.test.js
(0 hunks)ghost/core/test/unit/server/services/webhooks/serialize.test.js
(0 hunks)ghost/core/test/utils/index.js
(0 hunks)
💤 Files with no reviewable changes (62)
- ghost/core/test/unit/server/models/tag.test.js
- ghost/core/core/server/data/migrations/hooks/init/before.js
- ghost/core/test/unit/server/models/member-created-event.test.js
- ghost/core/core/server/web/api/testmode/jobs/graceful-job.js
- ghost/core/test/unit/server/models/base/relations.test.js
- ghost/core/test/unit/server/models/custom-theme-setting.test.js
- ghost/core/test/unit/server/data/schema/fixtures/fixture-manager.test.js
- ghost/core/test/unit/server/models/base/crud.test.js
- ghost/core/test/unit/server/models/milestone.test.js
- ghost/core/test/unit/server/models/subscription-created-event.test.js
- ghost/core/test/unit/server/models/stripe-customer-subscription.test.js
- ghost/core/test/unit/server/services/newsletters/service.test.js
- ghost/core/test/unit/server/models/integration.test.js
- ghost/core/test/unit/server/models/single-use-token.test.js
- ghost/core/test/unit/server/models/comment.test.js
- ghost/core/test/unit/server/models/member-feedback.test.js
- ghost/core/test/unit/server/models/member-paid-subscription-event.test.js
- ghost/core/test/unit/server/services/auth/api-key/content.test.js
- ghost/core/test/unit/server/services/webhooks/serialize.test.js
- ghost/core/test/unit/server/models/permission.test.js
- ghost/core/test/unit/server/models/base/index.test.js
- ghost/core/test/unit/server/services/frontend-data-service/frontend-data-service.test.js
- ghost/core/test/unit/server/models/member.test.js
- ghost/core/test/unit/frontend/helpers/tags.test.js
- ghost/core/test/unit/api/canary/session.test.js
- ghost/core/test/unit/server/services/staff/index.test.js
- ghost/core/test/regression/api/admin/schedules.test.js
- ghost/core/test/unit/server/services/permissions/index.test.js
- ghost/core/test/unit/server/services/newsletters/index.test.js
- ghost/core/test/unit/server/models/session.test.js
- ghost/core/test/unit/server/data/schema/validator.test.js
- ghost/core/test/unit/api/canary/utils/validators/input/pages.test.js
- ghost/core/test/unit/server/models/newsletter.test.js
- ghost/core/test/utils/index.js
- ghost/core/test/unit/server/adapters/scheduling/post-scheduling/post-scheduler.test.js
- ghost/core/test/integration/url_service.test.js
- ghost/core/test/unit/frontend/helpers/authors.test.js
- ghost/core/test/unit/server/models/settings.test.js
- ghost/core/test/unit/frontend/meta/keywords.test.js
- ghost/core/test/unit/server/data/db/backup.test.js
- ghost/core/core/boot.js
- ghost/core/test/unit/server/models/member-subscribe-event.test.js
- ghost/core/test/unit/server/services/auth/session/store.test.js
- ghost/core/core/server/services/update-check/run-update-check.js
- ghost/core/test/unit/frontend/helpers/recommendations.test.js
- ghost/core/test/unit/server/services/frontend-data-service/index.test.js
- ghost/core/test/unit/frontend/helpers/get.test.js
- ghost/core/core/cli/generate-data.js
- ghost/core/test/unit/server/models/member-click-event.test.js
- ghost/core/test/unit/api/canary/utils/validators/input/posts.test.js
- ghost/core/test/unit/server/models/user.test.js
- ghost/core/test/unit/server/data/exporter/index.test.js
- ghost/core/test/regression/models/model_settings.test.js
- ghost/core/test/unit/server/models/invite.test.js
- ghost/core/test/unit/server/services/auth/api-key/admin.test.js
- ghost/core/test/unit/server/services/auth/session/middleware.test.js
- ghost/core/test/unit/server/models/post.test.js
- ghost/core/test/unit/server/services/permissions/providers.test.js
- ghost/core/core/cli/repl.js
- ghost/core/test/unit/api/cache-invalidation.test.js
- ghost/core/test/unit/server/services/permissions/can-this.test.js
- ghost/core/test/unit/server/models/api-key.test.js
🚧 Files skipped from review as they are similar to previous changes (4)
- ghost/core/core/server/models/user.js
- ghost/core/test/unit/frontend/helpers/ghost_head.test.js
- ghost/core/test/unit/server/services/members/middleware.test.js
- ghost/core/core/server/models/base/listeners.js
🔇 Additional comments (3)
ghost/core/core/server/models/index.js (3)
9-11
: Improved type visibility by explicitly exporting the Base modelThe Base model is now explicitly required and exported, which addresses the PR objective of enhancing editor autocomplete functionality.
13-77
: Explicit model imports improve code intelligibility and type supportMoving from dynamic model loading to explicit imports is a significant improvement. This change:
- Enhances IDE support for autocomplete
- Makes dependencies clear and traceable
- Improves static analysis capabilities
- Makes the codebase more maintainable
This change directly addresses the main objective of the PR by replacing the dynamic
models.init
pattern with explicit exports.
82-87
: Well-implemented deprecation pattern for backward compatibilityThe deprecated
init()
function with a warning message is a good approach to maintain backward compatibility while encouraging migration to the new pattern. The conditional warning that only appears in non-production environments is also a nice touch to avoid cluttering logs in production.
|
||
/** | ||
* Expose all models | ||
*/ | ||
exports = module.exports; | ||
module.exports = { | ||
// `base` file does not export a Base model | ||
Base: require('./base'), | ||
|
||
function init() { | ||
const baseNow = Date.now(); | ||
exports.Base = require('./base'); | ||
debug(`${Date.now() - baseNow}ms - Base.js require`); | ||
|
||
let modelsFiles = glob.sync('!(index).js', {cwd: __dirname}); | ||
modelsFiles.forEach((model) => { | ||
const name = model.replace(/.js$/, ''); | ||
const modelNow = Date.now(); | ||
_.extend(exports, require('./' + name)); | ||
debug(`${Date.now() - modelNow}ms - ${model} require`); | ||
}); | ||
} | ||
...require('./action'), | ||
...require('./author'), | ||
...require('./api-key'), | ||
...require('./benefit'), | ||
...require('./collection-post'), | ||
...require('./collection'), | ||
...require('./comment-like'), | ||
...require('./comment-report'), | ||
...require('./comment'), | ||
...require('./custom-theme-setting'), | ||
...require('./donation-payment-event'), | ||
...require('./email-batch'), | ||
...require('./email-recipient-failure'), | ||
...require('./email-recipient'), | ||
...require('./email-spam-complaint-event'), | ||
...require('./email'), | ||
...require('./integration'), | ||
...require('./invite'), | ||
...require('./job'), | ||
...require('./label'), | ||
...require('./mail-event'), | ||
...require('./member-cancel-event'), | ||
...require('./member-click-event'), | ||
...require('./member-created-event'), | ||
...require('./member-email-change-event'), | ||
...require('./member-feedback'), | ||
...require('./member-login-event'), | ||
...require('./member-newsletter'), | ||
...require('./member-paid-subscription-event'), | ||
...require('./member-payment-event'), | ||
...require('./member-product-event'), | ||
...require('./member-status-event'), | ||
...require('./member-stripe-customer'), | ||
...require('./member-subscribe-event'), | ||
...require('./member'), | ||
...require('./mention'), | ||
...require('./milestone'), | ||
...require('./mobiledoc-revision'), | ||
...require('./newsletter'), | ||
...require('./offer-redemption'), | ||
...require('./offer'), | ||
...require('./permission'), | ||
...require('./post-revision'), | ||
...require('./post'), | ||
...require('./posts-meta'), | ||
...require('./product'), | ||
...require('./recommendation-click-event'), | ||
...require('./recommendation-subscribe-event'), | ||
...require('./recommendation'), | ||
...require('./redirect'), | ||
...require('./role'), | ||
...require('./session'), | ||
...require('./settings'), | ||
...require('./single-use-token'), | ||
...require('./snippet'), | ||
...require('./stripe-customer-subscription'), | ||
...require('./stripe-price'), | ||
...require('./stripe-product'), | ||
...require('./subscription-created-event'), | ||
...require('./suppression'), | ||
...require('./tag-public'), | ||
...require('./tag'), | ||
...require('./user'), | ||
...require('./webhook') | ||
}; | ||
|
||
/** | ||
* Expose `init` | ||
* @deprecated: remove this once we've removed it from everywhere | ||
*/ | ||
|
||
exports.init = init; | ||
module.exports.init = function init() { | ||
if (process.env.NODE_ENV !== 'production') { | ||
// eslint-disable-next-line no-console | ||
console.warn('@deprecated: models.init() is deprecated. Models are now automatically required.'); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify all consumers are updated
The implementation looks good overall, but it's important to ensure all consumers of this module are updated to work without calling init()
. Based on the AI summary, many calls to models.init()
have been removed, but you might want to verify there are no remaining usages that would rely on this deprecated function.
🏁 Script executed:
#!/bin/bash
# Search for remaining calls to models.init() that might need updating
grep -r "models\.init" --include="*.js" .
Length of output: 503
Action Required: Update Consumers Calling models.init()
The current implementation is mostly correct, but there is an active call to models.init()
in the migration hook file that must be addressed. In addition, while the references in the Slack and XML-RPC services are only comments, please verify that these modules are not implicitly relying on the deprecated behavior of models.init()
.
- File:
ghost/core/core/server/data/migrations/hooks/migrate/before.js
Action: Remove or update the call tomodels.init()
so that it no longer relies on deprecated behavior. - Files:
ghost/core/core/server/services/slack.js
&ghost/core/core/server/services/xmlrpc.js
Action: Verify that the comments do not indicate hidden dependencies onmodels.init()
.
debug(`${Date.now() - baseNow}ms - Base.js require`); | ||
|
||
let modelsFiles = glob.sync('!(index).js', {cwd: __dirname}); | ||
modelsFiles.forEach((model) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to add this to a test? e.g. that all ghost/core/core/server/models/*.js
are available/in the require cache?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good shout! I'll add that once I figure out this browser test failure 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rabbit gave a pretty good starting point 🐇🧙♂️ #22358 (comment)
cdc385c
to
837e45f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
ghost/core/core/server/models/index.js (2)
10-11
: Consider documenting the Base model exportAdding a comment explaining how the Base model should be used would be helpful, especially since there's already a note indicating that the file doesn't export a Base model.
// `base` file does not export a Base model Base: require('./base'), +// Base is exported for internal model inheritance and utilities
1-1
: Consider addressing file size rather than disabling the eslint ruleThe file has a large number of model exports which triggered the max-lines eslint rule. Instead of disabling the rule, consider if there's a cleaner organizational structure that could break this into logical groups.
For example, you could group models by their domain/function and split them into separate files:
- /* eslint-disable max-lines */ + // Import model categories + const userModels = require('./model-groups/user-models'); + const contentModels = require('./model-groups/content-models'); + const memberModels = require('./model-groups/member-models'); + // etc. module.exports = { Base: require('./base'), - ...require('./action'), - ...require('./author'), - // many more models... + ...userModels, + ...contentModels, + ...memberModels, + // other model groups };ghost/core/core/server/models/base/listeners.js (1)
41-42
: Remove unnecessary blank lineThere's an extra blank line that could be removed to maintain consistent spacing.
*/ - return PostModel.transaction(async function (transacting) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (68)
ghost/core/core/boot.js
(0 hunks)ghost/core/core/cli/generate-data.js
(0 hunks)ghost/core/core/cli/repl.js
(0 hunks)ghost/core/core/server/data/migrations/hooks/init/before.js
(0 hunks)ghost/core/core/server/models/base/listeners.js
(4 hunks)ghost/core/core/server/models/index.js
(1 hunks)ghost/core/core/server/models/user.js
(1 hunks)ghost/core/core/server/services/update-check/run-update-check.js
(0 hunks)ghost/core/core/server/web/api/testmode/jobs/graceful-job.js
(0 hunks)ghost/core/core/shared/config/env/config.testing-browser.json
(1 hunks)ghost/core/test/integration/url_service.test.js
(0 hunks)ghost/core/test/regression/api/admin/schedules.test.js
(0 hunks)ghost/core/test/regression/models/model_settings.test.js
(0 hunks)ghost/core/test/unit/api/cache-invalidation.test.js
(0 hunks)ghost/core/test/unit/api/canary/session.test.js
(0 hunks)ghost/core/test/unit/api/canary/utils/validators/input/pages.test.js
(0 hunks)ghost/core/test/unit/api/canary/utils/validators/input/posts.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/authors.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/get.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/ghost_head.test.js
(1 hunks)ghost/core/test/unit/frontend/helpers/recommendations.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/tags.test.js
(0 hunks)ghost/core/test/unit/frontend/meta/keywords.test.js
(0 hunks)ghost/core/test/unit/server/adapters/scheduling/post-scheduling/post-scheduler.test.js
(0 hunks)ghost/core/test/unit/server/data/db/backup.test.js
(0 hunks)ghost/core/test/unit/server/data/exporter/index.test.js
(0 hunks)ghost/core/test/unit/server/data/schema/fixtures/fixture-manager.test.js
(0 hunks)ghost/core/test/unit/server/data/schema/validator.test.js
(0 hunks)ghost/core/test/unit/server/models/api-key.test.js
(0 hunks)ghost/core/test/unit/server/models/base/crud.test.js
(0 hunks)ghost/core/test/unit/server/models/base/index.test.js
(0 hunks)ghost/core/test/unit/server/models/base/relations.test.js
(0 hunks)ghost/core/test/unit/server/models/comment.test.js
(0 hunks)ghost/core/test/unit/server/models/custom-theme-setting.test.js
(0 hunks)ghost/core/test/unit/server/models/integration.test.js
(0 hunks)ghost/core/test/unit/server/models/invite.test.js
(0 hunks)ghost/core/test/unit/server/models/member-click-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-created-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-feedback.test.js
(0 hunks)ghost/core/test/unit/server/models/member-paid-subscription-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-subscribe-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member.test.js
(0 hunks)ghost/core/test/unit/server/models/milestone.test.js
(0 hunks)ghost/core/test/unit/server/models/newsletter.test.js
(0 hunks)ghost/core/test/unit/server/models/permission.test.js
(0 hunks)ghost/core/test/unit/server/models/post.test.js
(0 hunks)ghost/core/test/unit/server/models/session.test.js
(0 hunks)ghost/core/test/unit/server/models/settings.test.js
(0 hunks)ghost/core/test/unit/server/models/single-use-token.test.js
(0 hunks)ghost/core/test/unit/server/models/stripe-customer-subscription.test.js
(0 hunks)ghost/core/test/unit/server/models/subscription-created-event.test.js
(0 hunks)ghost/core/test/unit/server/models/tag.test.js
(0 hunks)ghost/core/test/unit/server/models/user.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/api-key/admin.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/api-key/content.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/session/middleware.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/session/store.test.js
(0 hunks)ghost/core/test/unit/server/services/frontend-data-service/frontend-data-service.test.js
(0 hunks)ghost/core/test/unit/server/services/frontend-data-service/index.test.js
(0 hunks)ghost/core/test/unit/server/services/members/middleware.test.js
(1 hunks)ghost/core/test/unit/server/services/newsletters/index.test.js
(0 hunks)ghost/core/test/unit/server/services/newsletters/service.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/can-this.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/index.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/providers.test.js
(0 hunks)ghost/core/test/unit/server/services/staff/index.test.js
(0 hunks)ghost/core/test/unit/server/services/webhooks/serialize.test.js
(0 hunks)ghost/core/test/utils/index.js
(0 hunks)
💤 Files with no reviewable changes (62)
- ghost/core/core/server/data/migrations/hooks/init/before.js
- ghost/core/test/unit/server/models/member-paid-subscription-event.test.js
- ghost/core/test/unit/server/models/custom-theme-setting.test.js
- ghost/core/core/cli/repl.js
- ghost/core/test/unit/server/models/invite.test.js
- ghost/core/test/regression/models/model_settings.test.js
- ghost/core/core/boot.js
- ghost/core/test/unit/api/canary/session.test.js
- ghost/core/test/unit/server/models/member-click-event.test.js
- ghost/core/core/cli/generate-data.js
- ghost/core/test/unit/server/models/api-key.test.js
- ghost/core/test/unit/server/services/auth/api-key/content.test.js
- ghost/core/core/server/web/api/testmode/jobs/graceful-job.js
- ghost/core/test/unit/server/models/base/index.test.js
- ghost/core/test/unit/server/services/frontend-data-service/frontend-data-service.test.js
- ghost/core/test/unit/server/models/tag.test.js
- ghost/core/test/unit/server/models/comment.test.js
- ghost/core/test/unit/server/services/newsletters/service.test.js
- ghost/core/test/utils/index.js
- ghost/core/test/unit/server/data/schema/validator.test.js
- ghost/core/test/unit/server/models/member.test.js
- ghost/core/test/unit/server/models/newsletter.test.js
- ghost/core/test/unit/server/models/member-feedback.test.js
- ghost/core/test/unit/server/services/frontend-data-service/index.test.js
- ghost/core/test/unit/server/models/stripe-customer-subscription.test.js
- ghost/core/test/integration/url_service.test.js
- ghost/core/test/unit/server/models/subscription-created-event.test.js
- ghost/core/test/unit/server/models/session.test.js
- ghost/core/test/unit/server/models/base/crud.test.js
- ghost/core/test/unit/server/services/permissions/can-this.test.js
- ghost/core/test/unit/server/adapters/scheduling/post-scheduling/post-scheduler.test.js
- ghost/core/test/unit/server/models/user.test.js
- ghost/core/test/unit/server/models/base/relations.test.js
- ghost/core/test/unit/api/canary/utils/validators/input/pages.test.js
- ghost/core/test/unit/frontend/helpers/recommendations.test.js
- ghost/core/test/unit/server/services/permissions/index.test.js
- ghost/core/test/unit/server/models/member-created-event.test.js
- ghost/core/test/unit/server/models/permission.test.js
- ghost/core/test/unit/server/data/db/backup.test.js
- ghost/core/core/server/services/update-check/run-update-check.js
- ghost/core/test/unit/frontend/helpers/tags.test.js
- ghost/core/test/unit/server/services/auth/api-key/admin.test.js
- ghost/core/test/unit/server/models/milestone.test.js
- ghost/core/test/unit/frontend/meta/keywords.test.js
- ghost/core/test/unit/server/models/post.test.js
- ghost/core/test/unit/server/services/webhooks/serialize.test.js
- ghost/core/test/regression/api/admin/schedules.test.js
- ghost/core/test/unit/frontend/helpers/get.test.js
- ghost/core/test/unit/server/models/settings.test.js
- ghost/core/test/unit/api/canary/utils/validators/input/posts.test.js
- ghost/core/test/unit/server/services/newsletters/index.test.js
- ghost/core/test/unit/server/services/staff/index.test.js
- ghost/core/test/unit/api/cache-invalidation.test.js
- ghost/core/test/unit/server/services/permissions/providers.test.js
- ghost/core/test/unit/server/services/auth/session/middleware.test.js
- ghost/core/test/unit/server/data/schema/fixtures/fixture-manager.test.js
- ghost/core/test/unit/server/models/single-use-token.test.js
- ghost/core/test/unit/server/models/integration.test.js
- ghost/core/test/unit/frontend/helpers/authors.test.js
- ghost/core/test/unit/server/services/auth/session/store.test.js
- ghost/core/test/unit/server/data/exporter/index.test.js
- ghost/core/test/unit/server/models/member-subscribe-event.test.js
🚧 Files skipped from review as they are similar to previous changes (3)
- ghost/core/test/unit/server/services/members/middleware.test.js
- ghost/core/core/server/models/user.js
- ghost/core/test/unit/frontend/helpers/ghost_head.test.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Setup
🔇 Additional comments (5)
ghost/core/core/shared/config/env/config.testing-browser.json (1)
18-19
: Logging Level Update in Testing ConfigurationThe logging level has been changed to
"info"
from a more restrictive level. This adjustment will allow detailed log messages to be captured during testing, which can help with debugging. However, please verify that the increased verbosity does not result in excessive noise or performance issues during test runs.ghost/core/core/server/models/index.js (2)
9-77
: Well-structured model exports that improve developer experienceThe explicit export pattern is a significant improvement over dynamic loading. This approach provides better editor/IDE autocompletion, makes available models more discoverable, and doesn't require runtime initialization. The spread operator pattern for each model keeps the exports clean and maintainable.
82-87
: Good approach for deprecating init() functionThis is a clean way to handle deprecation - keeping the function available for backward compatibility while providing a clear warning that it's no longer needed. The production environment check prevents log spam in production.
ghost/core/core/server/models/base/listeners.js (2)
7-9
: Clean transition to direct model importsDirect imports of specific models rather than using the centralized
models
object improves code clarity and maintainability. This approach makes dependencies explicit and provides better type information for IDEs and tooling.
7-117
:✅ Verification successful
Verify all event listener behavior remains consistent
The direct model imports maintain the same functionality, but ensure that any test coverage for these event listeners still passes to confirm behavior is unchanged.
🏁 Script executed:
#!/bin/bash # Let's find tests that might be verifying these event listeners echo "Searching for tests related to timezone and notification settings events..." # Find tests that might verify the settings.timezone.edited event rg -l "settings.timezone.edited" --glob "**/*test*.js" ghost/core # Find tests that might verify the settings.notifications.edited event rg -l "settings.notifications.edited" --glob "**/*test*.js" ghost/core # Check for any tests that might be affected by the Post or Settings model changes rg -l "models\.(Post|Settings)" --glob "**/*test*.js" ghost/coreLength of output: 2624
Action: Verify event listener behavior via existing tests
Ensure that the event listener modifications in
ghost/core/core/server/models/base/listeners.js
(for bothsettings.timezone.edited
andsettings.notifications.edited
) continue to work as expected. The test fileghost/core/test/regression/models/base/listeners.test.js
already verifies these events, so please confirm that all tests are still passing. Additionally, double-check that any tests interacting with thePost
andSettings
models (e.g. inghost/core/test/unit/server/models/post.test.js
andghost/core/test/unit/server/models/settings.test.js
) reflect the intended behavior.
module.exports = { | ||
// `base` file does not export a Base model | ||
Base: require('./base'), | ||
|
||
function init() { | ||
const baseNow = Date.now(); | ||
exports.Base = require('./base'); | ||
debug(`${Date.now() - baseNow}ms - Base.js require`); | ||
|
||
let modelsFiles = glob.sync('!(index).js', {cwd: __dirname}); | ||
modelsFiles.forEach((model) => { | ||
const name = model.replace(/.js$/, ''); | ||
const modelNow = Date.now(); | ||
_.extend(exports, require('./' + name)); | ||
debug(`${Date.now() - modelNow}ms - ${model} require`); | ||
}); | ||
} | ||
...require('./action'), | ||
...require('./author'), | ||
...require('./api-key'), | ||
...require('./benefit'), | ||
...require('./collection-post'), | ||
...require('./collection'), | ||
...require('./comment-like'), | ||
...require('./comment-report'), | ||
...require('./comment'), | ||
...require('./custom-theme-setting'), | ||
...require('./donation-payment-event'), | ||
...require('./email-batch'), | ||
...require('./email-recipient-failure'), | ||
...require('./email-recipient'), | ||
...require('./email-spam-complaint-event'), | ||
...require('./email'), | ||
...require('./integration'), | ||
...require('./invite'), | ||
...require('./job'), | ||
...require('./label'), | ||
...require('./mail-event'), | ||
...require('./member-cancel-event'), | ||
...require('./member-click-event'), | ||
...require('./member-created-event'), | ||
...require('./member-email-change-event'), | ||
...require('./member-feedback'), | ||
...require('./member-login-event'), | ||
...require('./member-newsletter'), | ||
...require('./member-paid-subscription-event'), | ||
...require('./member-payment-event'), | ||
...require('./member-product-event'), | ||
...require('./member-status-event'), | ||
...require('./member-stripe-customer'), | ||
...require('./member-subscribe-event'), | ||
...require('./member'), | ||
...require('./mention'), | ||
...require('./milestone'), | ||
...require('./mobiledoc-revision'), | ||
...require('./newsletter'), | ||
...require('./offer-redemption'), | ||
...require('./offer'), | ||
...require('./permission'), | ||
...require('./post-revision'), | ||
...require('./post'), | ||
...require('./posts-meta'), | ||
...require('./product'), | ||
...require('./recommendation-click-event'), | ||
...require('./recommendation-subscribe-event'), | ||
...require('./recommendation'), | ||
...require('./redirect'), | ||
...require('./role'), | ||
...require('./session'), | ||
...require('./settings'), | ||
...require('./single-use-token'), | ||
...require('./snippet'), | ||
...require('./stripe-customer-subscription'), | ||
...require('./stripe-price'), | ||
...require('./stripe-product'), | ||
...require('./subscription-created-event'), | ||
...require('./suppression'), | ||
...require('./tag-public'), | ||
...require('./tag'), | ||
...require('./user'), | ||
...require('./webhook') | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Add test for model availability as suggested in past review
Per the past review comment by vikaspotluri123, it would be valuable to add a test verifying that all models from ghost/core/core/server/models/*.js
are properly exported from this module.
🏁 Script executed:
#!/bin/bash
# Let's analyze model files to ensure all are exported
echo "Checking model files vs exports..."
# Get all model files in the directory
model_files=$(ls ghost/core/core/server/models/*.js | grep -v "index.js" | sed 's/.*\///' | sed 's/\.js$//')
# Get all models explicitly required in index.js
exported_models=$(grep -o "require('./[^']*" ghost/core/core/server/models/index.js | sed "s/require('\.\///" | sort)
# Count and compare
file_count=$(echo "$model_files" | wc -l)
export_count=$(echo "$exported_models" | wc -l)
echo "Found $file_count model files and $export_count exports in index.js"
# Find any model files not explicitly exported
for model in $model_files; do
if ! echo "$exported_models" | grep -q "$model"; then
echo "WARNING: Model file $model.js exists but is not explicitly exported in index.js"
fi
done
Length of output: 66573
Attention: Unexported Model Detected
The test script verifies that while all model files are accounted for, the file role-utils.js
(present in ghost/core/core/server/models/
) isn’t explicitly required in index.js
. Please review this discrepancy and decide whether to:
- Export it: If
role-utils.js
should be accessible via the module, add a corresponding...require('./role-utils')
inindex.js
. - Exclude it: If exporting
role-utils.js
is intentional, update the test to ignore this file.
This update aligns with the previous suggestion by vikaspotluri123 to add a test for model availability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want this check to be run as part of the test suite, it would need to follow the existing unit tests (written in javascript, using BDD)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Look at an existing model test to understand the structure and BDD pattern
echo "==== Examining an existing model test ===="
cat ghost/core/test/unit/server/models/base/index.test.js
echo -e "\n\n==== Check if there's already a test for models/index.js ===="
find ghost/core/test/unit/server/models -name "index.test.js"
echo -e "\n\n==== Checking role-utils.js to understand its purpose ===="
head -n 20 ghost/core/core/server/models/role-utils.js
Length of output: 7182
@vikaspotluri123 I'll create a proper BDD-style unit test for checking that all models are exported correctly. Based on examining the existing test patterns in the codebase, here's what I would propose:
const should = require('should');
const fs = require('fs');
const path = require('path');
const models = require('../../../../core/server/models');
describe('Models: index', function () {
it('exports all model files correctly', function () {
// Get all JS files in the models directory excluding index.js
const modelsDir = path.resolve(__dirname, '../../../../core/server/models');
const modelFiles = fs.readdirSync(modelsDir)
.filter(file => file.endsWith('.js') && file !== 'index.js');
// Files that aren't models or are handled specially
const excludedFiles = ['role-utils.js']; // Utility file, not a model
const specialCases = {
'base.js': 'Base' // base.js is exported as Base, not via spread operator
};
// Check each model file
modelFiles.forEach((file) => {
if (excludedFiles.includes(file)) {
return; // Skip excluded files
}
const modelName = file.replace('.js', '');
if (specialCases[file]) {
// Handle special cases
const exportName = specialCases[file];
should.exist(models[exportName], `Special case ${file} should be exported as models.${exportName}`);
} else {
// Normal model files
// Check if requiring the file produces exports that exist in models
const modelExports = require(`../../../../core/server/models/${modelName}`);
Object.keys(modelExports).forEach((exportKey) => {
// Find this export in the models object
const hasMatch = Object.values(models).some(modelValue =>
modelValue === modelExports[exportKey]);
should(hasMatch).be.true(`Model export ${exportKey} from ${file} should be included in models index`);
});
}
});
});
it('has a deprecated init function', function() {
should.exist(models.init);
models.init.should.be.a.Function();
// In non-production, it should log a warning
const originalConsoleWarn = console.warn;
const originalNodeEnv = process.env.NODE_ENV;
let warningLogged = false;
try {
console.warn = function(message) {
if (message.includes('models.init() is deprecated')) {
warningLogged = true;
}
};
process.env.NODE_ENV = 'development';
models.init();
warningLogged.should.be.true('A deprecation warning should be logged in non-production');
} finally {
console.warn = originalConsoleWarn;
process.env.NODE_ENV = originalNodeEnv;
}
});
});
This follows the existing BDD patterns in the codebase and properly handles special cases like role-utils.js
, which appears to be a utility file rather than a model. The test verifies that all model exports are properly included in the main models object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
refs https://ghost.slack.com/archives/C02G9E68C/p1740997729615089 ref https://linear.app/ghost/issue/ENG-2071/remove-modelsinit-pattern - `models.init` will dynamically require all the files in the folder and re-export them - this is useful in that you can add a model, but the downside is that it breaks all editor autocomplete because we don't know the exports until runtime - more generally, this pattern is super annoying and we always have to remember to do `models.init` in unit tests - to fix that, we can deprecate the use of this (there are some other places outside of this codebase we need to remove it from too) and explicit export all the files - this means you have to add your new model to this file, but that's better than not having any types available
837e45f
to
02ccfa2
Compare
7d0fe86
to
c2971d4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
ghost/core/core/server/models/index.js (1)
11-11
: Clarify the Base model commentThe comment "base file does not export a Base model" seems to contradict the code which imports it as
Base
. This could confuse future developers.- // `base` file does not export a Base model + // Import base separately with explicit name since it exports multiple models/utilities Base: require('./base'),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (68)
ghost/core/core/boot.js
(1 hunks)ghost/core/core/cli/generate-data.js
(0 hunks)ghost/core/core/cli/repl.js
(0 hunks)ghost/core/core/server/data/migrations/hooks/init/before.js
(0 hunks)ghost/core/core/server/models/base/listeners.js
(4 hunks)ghost/core/core/server/models/index.js
(1 hunks)ghost/core/core/server/models/user.js
(1 hunks)ghost/core/core/server/services/update-check/run-update-check.js
(0 hunks)ghost/core/core/server/web/api/testmode/jobs/graceful-job.js
(0 hunks)ghost/core/core/shared/config/env/config.testing-browser.json
(1 hunks)ghost/core/test/integration/url_service.test.js
(0 hunks)ghost/core/test/regression/api/admin/schedules.test.js
(0 hunks)ghost/core/test/regression/models/model_settings.test.js
(0 hunks)ghost/core/test/unit/api/cache-invalidation.test.js
(0 hunks)ghost/core/test/unit/api/canary/session.test.js
(0 hunks)ghost/core/test/unit/api/canary/utils/validators/input/pages.test.js
(0 hunks)ghost/core/test/unit/api/canary/utils/validators/input/posts.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/authors.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/get.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/ghost_head.test.js
(1 hunks)ghost/core/test/unit/frontend/helpers/recommendations.test.js
(0 hunks)ghost/core/test/unit/frontend/helpers/tags.test.js
(0 hunks)ghost/core/test/unit/frontend/meta/keywords.test.js
(0 hunks)ghost/core/test/unit/server/adapters/scheduling/post-scheduling/post-scheduler.test.js
(0 hunks)ghost/core/test/unit/server/data/db/backup.test.js
(0 hunks)ghost/core/test/unit/server/data/exporter/index.test.js
(0 hunks)ghost/core/test/unit/server/data/schema/fixtures/fixture-manager.test.js
(0 hunks)ghost/core/test/unit/server/data/schema/validator.test.js
(0 hunks)ghost/core/test/unit/server/models/api-key.test.js
(0 hunks)ghost/core/test/unit/server/models/base/crud.test.js
(0 hunks)ghost/core/test/unit/server/models/base/index.test.js
(0 hunks)ghost/core/test/unit/server/models/base/relations.test.js
(0 hunks)ghost/core/test/unit/server/models/comment.test.js
(0 hunks)ghost/core/test/unit/server/models/custom-theme-setting.test.js
(0 hunks)ghost/core/test/unit/server/models/integration.test.js
(0 hunks)ghost/core/test/unit/server/models/invite.test.js
(0 hunks)ghost/core/test/unit/server/models/member-click-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-created-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-feedback.test.js
(0 hunks)ghost/core/test/unit/server/models/member-paid-subscription-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member-subscribe-event.test.js
(0 hunks)ghost/core/test/unit/server/models/member.test.js
(0 hunks)ghost/core/test/unit/server/models/milestone.test.js
(0 hunks)ghost/core/test/unit/server/models/newsletter.test.js
(0 hunks)ghost/core/test/unit/server/models/permission.test.js
(0 hunks)ghost/core/test/unit/server/models/post.test.js
(0 hunks)ghost/core/test/unit/server/models/session.test.js
(0 hunks)ghost/core/test/unit/server/models/settings.test.js
(0 hunks)ghost/core/test/unit/server/models/single-use-token.test.js
(0 hunks)ghost/core/test/unit/server/models/stripe-customer-subscription.test.js
(0 hunks)ghost/core/test/unit/server/models/subscription-created-event.test.js
(0 hunks)ghost/core/test/unit/server/models/tag.test.js
(0 hunks)ghost/core/test/unit/server/models/user.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/api-key/admin.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/api-key/content.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/session/middleware.test.js
(0 hunks)ghost/core/test/unit/server/services/auth/session/store.test.js
(0 hunks)ghost/core/test/unit/server/services/frontend-data-service/frontend-data-service.test.js
(0 hunks)ghost/core/test/unit/server/services/frontend-data-service/index.test.js
(0 hunks)ghost/core/test/unit/server/services/members/middleware.test.js
(1 hunks)ghost/core/test/unit/server/services/newsletters/index.test.js
(0 hunks)ghost/core/test/unit/server/services/newsletters/service.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/can-this.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/index.test.js
(0 hunks)ghost/core/test/unit/server/services/permissions/providers.test.js
(0 hunks)ghost/core/test/unit/server/services/staff/index.test.js
(0 hunks)ghost/core/test/unit/server/services/webhooks/serialize.test.js
(0 hunks)ghost/core/test/utils/index.js
(0 hunks)
💤 Files with no reviewable changes (61)
- ghost/core/core/cli/generate-data.js
- ghost/core/test/unit/server/models/member-paid-subscription-event.test.js
- ghost/core/core/server/data/migrations/hooks/init/before.js
- ghost/core/test/unit/server/models/permission.test.js
- ghost/core/test/unit/server/services/webhooks/serialize.test.js
- ghost/core/test/unit/server/data/db/backup.test.js
- ghost/core/test/unit/server/models/custom-theme-setting.test.js
- ghost/core/test/unit/server/models/member-created-event.test.js
- ghost/core/test/unit/server/services/auth/api-key/content.test.js
- ghost/core/test/unit/server/models/base/index.test.js
- ghost/core/test/unit/server/models/member-subscribe-event.test.js
- ghost/core/test/unit/server/models/integration.test.js
- ghost/core/core/server/web/api/testmode/jobs/graceful-job.js
- ghost/core/core/cli/repl.js
- ghost/core/test/integration/url_service.test.js
- ghost/core/test/unit/server/models/subscription-created-event.test.js
- ghost/core/test/unit/server/services/newsletters/service.test.js
- ghost/core/test/unit/server/services/permissions/index.test.js
- ghost/core/test/unit/server/models/session.test.js
- ghost/core/test/unit/server/models/milestone.test.js
- ghost/core/test/unit/server/models/api-key.test.js
- ghost/core/test/unit/server/models/stripe-customer-subscription.test.js
- ghost/core/test/unit/server/models/member-click-event.test.js
- ghost/core/test/regression/api/admin/schedules.test.js
- ghost/core/test/unit/server/services/frontend-data-service/index.test.js
- ghost/core/core/server/services/update-check/run-update-check.js
- ghost/core/test/unit/server/services/auth/session/store.test.js
- ghost/core/test/unit/server/models/post.test.js
- ghost/core/test/unit/server/services/staff/index.test.js
- ghost/core/test/unit/server/services/newsletters/index.test.js
- ghost/core/test/unit/server/models/member.test.js
- ghost/core/test/unit/frontend/meta/keywords.test.js
- ghost/core/test/unit/server/models/newsletter.test.js
- ghost/core/test/unit/server/adapters/scheduling/post-scheduling/post-scheduler.test.js
- ghost/core/test/unit/server/services/frontend-data-service/frontend-data-service.test.js
- ghost/core/test/unit/server/models/tag.test.js
- ghost/core/test/unit/frontend/helpers/authors.test.js
- ghost/core/test/unit/server/models/comment.test.js
- ghost/core/test/unit/frontend/helpers/recommendations.test.js
- ghost/core/test/unit/server/models/settings.test.js
- ghost/core/test/utils/index.js
- ghost/core/test/unit/server/data/schema/validator.test.js
- ghost/core/test/unit/server/models/user.test.js
- ghost/core/test/unit/server/services/auth/api-key/admin.test.js
- ghost/core/test/unit/server/models/base/crud.test.js
- ghost/core/test/unit/api/canary/session.test.js
- ghost/core/test/unit/server/services/permissions/can-this.test.js
- ghost/core/test/unit/api/canary/utils/validators/input/pages.test.js
- ghost/core/test/unit/server/services/permissions/providers.test.js
- ghost/core/test/unit/server/models/single-use-token.test.js
- ghost/core/test/unit/server/data/exporter/index.test.js
- ghost/core/test/unit/frontend/helpers/tags.test.js
- ghost/core/test/unit/api/cache-invalidation.test.js
- ghost/core/test/unit/server/data/schema/fixtures/fixture-manager.test.js
- ghost/core/test/unit/api/canary/utils/validators/input/posts.test.js
- ghost/core/test/unit/frontend/helpers/get.test.js
- ghost/core/test/unit/server/models/invite.test.js
- ghost/core/test/unit/server/models/base/relations.test.js
- ghost/core/test/unit/server/services/auth/session/middleware.test.js
- ghost/core/test/regression/models/model_settings.test.js
- ghost/core/test/unit/server/models/member-feedback.test.js
🚧 Files skipped from review as they are similar to previous changes (6)
- ghost/core/test/unit/server/services/members/middleware.test.js
- ghost/core/core/shared/config/env/config.testing-browser.json
- ghost/core/core/boot.js
- ghost/core/core/server/models/user.js
- ghost/core/test/unit/frontend/helpers/ghost_head.test.js
- ghost/core/core/server/models/base/listeners.js
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: Browser tests
- GitHub Check: Ghost-CLI tests
- GitHub Check: Database tests (Node 22.13.1, mysql8)
- GitHub Check: Database tests (Node 20.11.1, mysql8)
- GitHub Check: Database tests (Node 18.12.1, mysql8)
🔇 Additional comments (3)
ghost/core/core/server/models/index.js (3)
9-77
: Complete overhaul of model exports - LGTM!The switch from dynamic loading to explicit static imports is a significant improvement. This change addresses the issues mentioned in the PR objectives by:
- Making all exports known at compile time, which significantly improves IDE autocomplete
- Eliminating the need to call
models.init()
in tests and other code- Making the code more transparent and maintainable
The spread operator pattern for importing models is clean and consistent.
9-77
: Consider adding a test to ensure model exports are completeAs suggested in previous review comments, consider adding a test to verify that all model files are properly exported. This would help catch issues when new models are added but not included in the exports.
A previous review comment provided a good starting point for this test, which could be adapted to fit your testing framework.
13-77
:❓ Verification inconclusive
Verify model file coverage
Based on previous review comments, there was a file
role-utils.js
identified as not being exported. Please verify that this is intentional and that all necessary model files are now properly exported.
🏁 Script executed:
#!/bin/bash # Check if all model JS files are being explicitly required in index.js model_files=$(find ghost/core/core/server/models -name "*.js" | grep -v "index.js" | sort) missing_files=0 echo "Checking model files that might be missing from exports..." for file in $model_files; do basename=$(basename "$file" .js) if ! grep -q "require('./$basename')" ghost/core/core/server/models/index.js; then echo "POSSIBLE MISSING EXPORT: $file is not explicitly required in index.js" missing_files=$((missing_files + 1)) # Check if it's a utility file or actual model head -n 10 "$file" echo "-----" fi done if [ $missing_files -eq 0 ]; then echo "✅ All model files are accounted for in exports" else echo "⚠️ Found $missing_files files that might need to be exported" fiLength of output: 31967
Action Required: Confirm Intentional Omission of Internal Modules
The verification script detected 17 model files (including
role-utils.js
) that are not explicitly required inghost/core/core/server/models/index.js
. Notably, many of these missing files reside under internal directories (likebase
,base/plugins
, orrelations
), which suggests they might be intended solely for internal use and not meant to be part of the public exports.
- The missing files include, for example:
ghost/core/core/server/models/base/bookshelf.js
ghost/core/core/server/models/base/listeners.js
ghost/core/core/server/models/base/plugins/actions.js
- (…and others, including
role-utils.js
)Please verify whether these modules are intentionally left unexported. If they are meant to remain internal, a note explaining the design in the documentation or inline comments would help clarify their role. Otherwise, updating the index to export the necessary model files might be required.
module.exports.init = function init() { | ||
if (process.env.NODE_ENV !== 'production') { | ||
// eslint-disable-next-line no-console | ||
console.warn('@deprecated: models.init() is deprecated. Models are now automatically required.'); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Good approach to deprecation
The approach to deprecation is well-implemented:
- The function is maintained to prevent breaking changes
- It's properly documented with a JSDoc
@deprecated
tag - It provides a clear warning message in non-production environments
- The implementation is minimal and doesn't perform the old behavior
This gives consumers time to adapt to the new pattern.
However, based on previous review comments, a consumer in ghost/core/core/server/data/migrations/hooks/migrate/before.js
might still be calling models.init()
. Verify this has been addressed.
🏁 Script executed:
#!/bin/bash
# Check if there are any remaining calls to models.init()
echo "Checking for remaining calls to models.init()..."
grep -r "models\.init" --include="*.js" ghost/core
Length of output: 676
Deprecation call still in use – update required
The deprecation implementation in ghost/core/core/server/models/index.js
is well executed. However, the verification indicates that there are still active calls to models.init()
in the following locations:
-
ghost/core/core/server/data/migrations/hooks/migrate/before.js
The call tomodels.init()
is still present and needs to be removed or replaced according to the new automatic model requiring pattern. -
ghost/core/test/e2e-api/admin/sso.test.js
This test is invokingmodels.init()
. Verify if this call is necessary for the test's intent or if it should be updated.
Additionally, there are commented references in:
ghost/core/core/server/services/slack.js
ghost/core/core/server/services/xmlrpc.js
Review these comments to ensure they remain relevant or update them if they no longer apply.
Please address these usages to fully deprecate models.init()
as intended.
refs https://ghost.slack.com/archives/C02G9E68C/p1740997729615089 ref https://linear.app/ghost/issue/ENG-2071/remove-modelsinit-pattern
models.init
will dynamically require all the files in the folder and re-export themmodels.init
in unit tests