Repository navigation
Conversation
Add a Payload XLSX conversion flow for Herbatica blog content. Run the converter with:\n\n pnpm --filter @nmit/payload exec payload run src/scripts/convert-article-xlsx-html-to-richtext.ts /var/www/local/seed-files/blog_clanky.xlsx /var/www/local/seed-files/blog_clanky.richtext.xlsx\n\nThe converter writes a new richtext XLSX plus media and links manifests, gzip/base64 encodes Payload Lexical JSON for Excel cells, imports image references via media markers, strips hyperlink nodes while exporting link text/URLs, and converts ProductWidgets embeds into Lexical blocks. Product widgets become productCarousel blocks with productSlug values; article widgets become articleCarousel blocks with articleSlug values. Mixed widgets emit both blocks.\n\nAdd Payload blocks and admin pickers for productCarousel.products[].productSlug and articleCarousel.articles[].articleSlug. The pickers search Medusa products and Payload articles through protected endpoints while still storing only slug strings.\n\nUpdate Payload seeding so richtext XLSX content is decoded/imported, media manifests can prepare upload nodes, Herbatica product article seeding remains optional, and Payload container startup no longer seeds by default. The Herbatica Medusa seed script now runs migrations, executes the Medusa Herbatica seed, then invokes the Payload seed with PAYLOAD_SEED_* env mapped to the Payload runtime vars.\n\nTypical local flow:\n\n 1. Convert the XLSX to /var/www/local/seed-files/blog_clanky.richtext.xlsx.\n 2. Ensure PAYLOAD_SEED_* env points at the Payload DB/S3 config and richtext XLSX.\n 3. Run pnpm --filter medusa-be run seedHerbatica.\n\nThat runs Medusa migrations, seeds Herbatica Medusa data, then seeds Payload articles from the converted richtext workbook.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (4)
📜 Recent review details
|
| Layer / File(s) | Summary |
|---|---|
Carousel blocks and editor registration apps/payload/src/lib/blocks/*, apps/payload/src/lib/editors/lexical.ts |
Lexical registers article and product carousel blocks with custom slug fields and article slug validation. |
Admin slug pickers and lookup endpoints apps/payload/src/components/admin/*, apps/payload/src/lib/endpoints/*, apps/payload/src/lib/utils/endpoint.ts, apps/payload/src/payload.config.ts, apps/payload/src/app/(payload)/importMap.js |
Authenticated article and Medusa product lookup endpoints support debounced searchable admin selectors. |
Rich-text conversion and media import apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts, apps/payload/src/scripts/import-articles.ts |
XLSX HTML is converted to compressed Lexical content with carousel and media manifests, which the importer uploads and hydrates into Payload records. |
Herbatica seed ingestion apps/payload/src/seed.ts, apps/payload/README.md |
Repeatable slug-based seeding imports Herbatica product XML and optional blog article XLSX content. |
Seed configuration and execution wiring .env.docker, docker-compose.yaml, docker/development/payload/payload-runtime.sh, apps/medusa-be/src/scripts/herbatica-seed.ts |
Environment blocks define seed inputs and controls, startup seeding defaults to disabled, and the Herbatica workflow invokes Payload seeding as a child process. |
Estimated code review effort: 4 (Complex) | ~60 minutes
Sequence Diagram(s)
sequenceDiagram
participant XLSXConverter
participant importArticles
participant PayloadMedia
XLSXConverter->>importArticles: Pass compressed Lexical content and media manifest
importArticles->>PayloadMedia: Fetch and upsert referenced images
PayloadMedia-->>importArticles: Return media IDs
importArticles-->>importArticles: Replace media URL tokens with relations
Possibly related PRs
- TechsioCZ/new-engine#424: Updates the shared article importer used by this PR’s rich-text and media import flow.
- TechsioCZ/new-engine#450: Also modifies the Payload seeding pipeline’s hero-carousel behaviour.
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The title clearly matches the main change: importing Herbatica article widgets into Payload rich text. |
| Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
| Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
✨ Finishing Touches
📝 Generate docstrings
- Create stacked PR
- Commit on current branch
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Commit unit tests in branch
feat/payload-richtext-widget-seed-flow
✨ Simplify code
- Create PR with simplified code
- Commit simplified code in branch
feat/payload-richtext-widget-seed-flow
Warning
There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.
🔧 ESLint
If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.
ESLint install timed out. The project may have too many dependencies for the sandbox.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Greptile SummaryThis PR adds a Payload rich-text import and Herbatica seed flow. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (9): Last reviewed commit: "fix(payload): forward seed locale config..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 15
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/payload/src/lib/blocks/article-carousel.ts`:
- Around line 13-29: Add validation to the articleSlug field within the articles
array so submitted slugs are checked against existing articles during save,
using the Payload validation context to query the articles collection and return
a clear validation error when no match exists. Preserve the existing required
text-field and ArticleSlugField admin configuration.
In `@apps/payload/src/lib/endpoints/article-options.ts`:
- Around line 15-34: Move DEFAULT_LIMIT, MAX_LIMIT, parseLimit, and isAuthorized
from article-options.ts into ../utils/endpoint and export them alongside the
existing endpoint utilities. In
apps/payload/src/lib/endpoints/article-options.ts (lines 15-34), import and use
the shared symbols; in apps/payload/src/lib/endpoints/medusa-products.ts (lines
15-16 and 31-47), remove the duplicate constants and helper implementations and
import the shared symbols instead.
- Around line 66-75: Update the articles query in the find call to include a
select configuration containing only id, slug, title, and featuredImage.url,
while preserving the existing filters, sorting, localization, and pagination
options.
In `@apps/payload/src/lib/endpoints/medusa-products.ts`:
- Around line 70-75: Update the Medusa product fetch around the fetch call to
add a fallback timeout when the provided signal is absent or invalid. Preserve
req.signal cancellation when it is a valid AbortSignal, and ensure the request
is aborted after a bounded timeout so an unresponsive Medusa backend cannot hang
indefinitely.
In `@apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts`:
- Around line 234-240: Update fetchProductWidgetData and its callers to bound
remote requests with an explicit timeout or abort signal, and handle resolution
failures without replacing the widget with empty content: either propagate the
error to fail the cell conversion or preserve the original widget markup for
retry. Apply the same behavior to the related conversion flow around the
referenced widget-processing logic.
- Around line 472-479: Update the record.type === "link" branch in
sanitizeLexicalNode to preserve the hyperlink node in the returned Lexical
structure, or implement the corresponding link hydration path consumed by
import-articles.ts; do not return only sanitized children while merely recording
the URL in context.linkManifest. Ensure seeded articles retain functional links
rather than plain text.
- Around line 18-25: Replace the ad-hoc FieldLike type and recursive editor
traversal with Payload’s fieldAffectsData and fieldHasSubFields guards in the
editor lookup logic. Preserve the explicit traversal of tab fields, and use the
guards to safely identify data-affecting fields and recurse through supported
subfields in the existing conversion flow.
In `@apps/payload/src/scripts/import-articles.ts`:
- Around line 303-310: Update decodeRichTextValue and the import flow around its
callers so prefixed values that fail Base64, gzip, or JSON decoding are treated
as malformed and reported or skipped, never returned as visible plain text.
Preserve the existing plain-text fallback only for values without
RICH_TEXT_GZIP_PREFIX, and ensure malformed encoded rows do not continue through
article import.
- Around line 1051-1066: Update the excerpt fallback in the article data
construction to decode the compressed prefixed content once, extract its plain
Lexical text, and use the first 300 characters of that decoded text when no
excerpt column is present. Keep the existing column-based excerpt precedence and
pass the decoded content through the existing rich-text conversion flow without
repeatedly decoding it.
- Around line 344-375: Harden fetchMediaBuffer before downloading manifest
media: validate the initial URL and every redirect, reject loopback, private,
link-local, and cloud-metadata hosts or resolved addresses, and enforce a
request timeout. Stream the response with a strict maximum byte limit instead of
fully buffering unbounded data, and accept only supported image content types
after validating the final response.
- Around line 420-468: Update hydrateRichTextMedia to detect every media URL
absent from mediaUrlMap instead of substituting fallbackMediaId, and expose
those unresolved URLs to its caller. In the article import flow, use that result
to report each unresolved URL and fail or skip the affected article before
persistence. Preserve successful hydration for mapped media and the existing
placeholder behavior only where it is not an unresolved manifest URL.
In `@apps/payload/src/seed.ts`:
- Around line 557-560: Update getProductDescription so an empty decoded
DESCRIPTION is treated as missing and falls back to SHORT_DESCRIPTION before
returning the final empty string. Preserve the existing HTML extraction and
decoding behavior while ensuring the fallback occurs for both nullish and empty
DESCRIPTION results.
- Around line 283-305: Update upsertBySlug to use Payload’s CollectionSlug and
DataFromCollectionSlug generics, typing collection and data from the collection
slug so payload.update and payload.create no longer require as never casts.
Preserve the existing find, update, and create behavior while enforcing
generated schema types for the collection and seed data.
- Around line 260-274: Limit lookup projections to the fields actually consumed
by adding depth: 0 and a minimal id-only select to findOne in
apps/payload/src/seed.ts (lines 260-274), findSeedMedia in
apps/payload/src/seed.ts (lines 356-370), and the media filename lookup in
apps/payload/src/scripts/import-articles.ts (lines 383-393); preserve each
lookup’s existing filtering and result handling.
In `@docker-compose.yaml`:
- Around line 45-59: Complete Payload seed configuration propagation across
docker-compose.yaml lines 45-59, .env.docker lines 97-100, and
apps/medusa-be/package.json line 54. Add the missing article status, overwrite,
translate, sheet, product-enable, and limit mappings/templates, then explicitly
forward them in seedHerbatica or remove redundant inline assignments so
identically named PAYLOAD_SEED_* variables are inherited automatically.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a3da424a-2fe8-4710-a5ca-b1d8710ffe66
📒 Files selected for processing (19)
.env.docker.mise.tomlapps/medusa-be/package.jsonapps/payload/README.mdapps/payload/src/app/(payload)/importMap.jsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/payload-types.tsapps/payload/src/payload.config.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsdocker-compose.yamldocker/development/payload/payload-runtime.sh
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: Greptile Review
- GitHub Check: main
- GitHub Check: Analyze (javascript-typescript)
⚠️ CI failures not shown inline (1)
GitHub Check: Kilo Code Review: Kilo Code Review failed
Conclusion: failure
Review failed: The message could not be delivered
🧰 Additional context used
📓 Path-based instructions (14)
apps/payload/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/access-control.md)
apps/payload/**/*.{ts,tsx,js,jsx}: Implement the 'admin only' access pattern in Payload CMS by checking if user roles include 'admin' and returning a boolean result
Implement the 'admin or self' access pattern in Payload CMS by checking admin role first, then falling back to self-referential query constraints (e.g.,{ id: { equals: user?.id } })
Implement the 'authenticated or published' access pattern in Payload CMS by returning true for authenticated users and applying query constraints for public access to published documents
In Payload CMS Local API calls, setoverrideAccess: falsewhen passing auserparameter to ensure access control is enforced rather than bypassed
Do NOT rely on the default Local API behavior in Payload CMS, as access control is skipped by default (overrideAccess: true) - always explicitly setoverrideAccess: falsewhen implementing access control
apps/payload/**/*.{ts,tsx,js,jsx}: When performing nested operations in hooks, always passreqparameter to maintain transaction context across all-or-nothing database operations
Passreqtoreq.payload.find()calls within hooks to maintain atomic transaction context across MongoDB, PostgreSQL, and SQLite databases
Passreqtoreq.payload.update()calls within hooks to ensure changes are included in the same transaction and can be rolled back together on errors
Usepayload.db.beginTransaction(),payload.db.commitTransaction(), andpayload.db.rollbackTransaction()for manual transaction control when needed
apps/payload/**/*.{ts,tsx,js,jsx}: Custom endpoints in Payload are not authenticated by default. Always checkreq.userto verify user authentication before processing requests.
Usereq.payloadfor database operations instead of direct database access to ensure access control and hooks execute properly.
Use theaddDataAndFileToRequesthelper from Payload to handle both JSON parsing and file uploads in POST endpoints.
UseheadersWithCorshelper from Payload ...
Files:
apps/payload/src/app/(payload)/importMap.jsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/payload.config.tsapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/payload-types.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/seed.tsapps/payload/src/scripts/import-articles.ts
apps/payload/**/*.{ts,tsx,js,jsx,graphql}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/queries.md)
Use GraphQL queries with proper field selection, filtering (where), limiting (limit), and sorting (sort) when querying Payload CMS via GraphQL
Files:
apps/payload/src/app/(payload)/importMap.jsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/payload.config.tsapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/payload-types.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/seed.tsapps/payload/src/scripts/import-articles.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run Biome linting and formatting only on changed files using 'bunx biome check --write path/to/file'
Files:
apps/payload/src/app/(payload)/importMap.jsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/payload.config.tsapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/payload-types.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/seed.tsapps/payload/src/scripts/import-articles.ts
apps/payload/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/access-control-advanced.md)
apps/payload/**/*.{ts,tsx}: Implement locale-specific access control usingAccessfunction to check user authentication and locale, allowing authenticated users all locales and public users only English content
Implement device-specific access control usingAccessfunction to check user-agent headers, distinguishing between mobile and desktop access
Create IP-based access restriction using factory function that returns anAccessfunction checking x-forwarded-for or x-real-ip headers against allowed IP list
Implement time-based access control to restrict records to today's date range usingAccessfunction with createdAt date comparisons
Create time-based access factory function that returns recent records (last N days) for regular users while granting admins full access
Implement scheduled content access control distinguishing editors/admins who see all content from public users who see only content within publish/unpublish date windows
Implement subscription-based access control using asyncAccessfunction to verify active subscription status, with admin bypass
Create tier-based subscription access factory function that checks subscription tier hierarchy and returns false on inactive subscriptions or errors
Implement role-based access factory functioncreateRoleBasedAccessthat checks if user has any of the specified roles
Implement organization-scoped access factory functioncreateOrgScopedAccessthat restricts documents to user's organization IDs with optional admin bypass
Implement team-based access factory functioncreateTeamBasedAccessthat filters documents by user's team IDs with admin bypass
Implement time-limited access factory functioncreateTimeLimitedAccessthat restricts documents to last N days with admin bypass
Implement public + authenticated collection pattern where create/update/delete are restricted to admins/editors, read shows published content to public and all content to authenticated users
Implement self-service collection...
Files:
apps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/payload.config.tsapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/payload-types.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/seed.tsapps/payload/src/scripts/import-articles.ts
apps/payload/**/endpoints/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/AGENTS.md)
apps/payload/**/endpoints/**/*.{ts,tsx}: Always check authentication in custom endpoints before performing operations
UseAPIErrorfor proper error responses in custom endpoints
Usereq.payloadfor database operations within custom endpoints
Files:
apps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.ts
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Import UI components using the
@techsio/ui-kitnamespace, not@libs/ui, for runtime apps
Files:
apps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/payload.config.tsapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/payload-types.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/seed.tsapps/payload/src/scripts/import-articles.ts
apps/**/!(medusa-be)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use modern React patterns and React 19 for frontend applications in the monorepo
Files:
apps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/editors/lexical.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/blocks/product-carousel.tsapps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/payload.config.tsapps/payload/src/components/admin/medusa-product-slug-field.tsxapps/payload/src/payload-types.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/seed.tsapps/payload/src/scripts/import-articles.ts
**/package.json
📄 CodeRabbit inference engine (CLAUDE.md)
Use pnpm CLI to add dependencies; never edit package.json directly
Files:
apps/medusa-be/package.json
apps/payload/**/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/components.md)
apps/payload/**/components/**/*.{ts,tsx,js,jsx}: Use 'use client' directive for components requiring interactivity, hooks, state management, or event handlers in Payload CMS admin panel
Server Components (default) can use Local API directly, perform async operations, and access full Payload instance in Payload CMS custom components
Client Components in Payload CMS cannot receive non-serializable props (functions, class instances, etc.); use clientProps for serializable data and serverProps for non-serializable data
Use 'useFormFields' for optimized re-renders when accessing specific field values in Payload CMS, instead of useForm which re-renders on any field change
In Admin Panel UI, import from '@payloadcms/ui' for Payload components; in frontend code, use specific paths from '@payloadcms/ui/elements' to minimize bundle size
Use Server Components by default for Payload CMS custom components; only use Client Components when needing state, effects, event handlers, or browser APIs
Use useDocumentInfo hook in Payload CMS Client Components to access current document info (id, slug, collection)
Use useAuth hook in Payload CMS Client Components to access current user information within the admin panel
Use useTranslation hook in Payload CMS Client Components to access i18n translations and language information
Use getTranslation utility in Payload CMS Server Components to translate content using the i18n object
Use React.memo() for expensive Payload CMS custom components, implement proper key props in lists, and avoid inline function definitions in renders
All custom components receive default props (payload, i18n, locale) automatically from Payload CMS; access via component parameters or hooks
Files:
apps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/components/admin/medusa-product-slug-field.tsx
apps/payload/**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/components.md)
Use TypeScript types from Payload (TextFieldServerComponent, TextFieldClientComponent, TextFieldCellComponent) to ensure type safety for custom components
apps/payload/**/components/**/*.{ts,tsx}: All components in the Admin Panel are Server Components by default; use 'use client' directive only when state or browser APIs are needed
Optimize re-renders in Client Components by usinguseFormFieldsinstead ofuseFormfor single field values
Import Payload UI components from '@payloadcms/ui' in Admin Panel components
Files:
apps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/components/admin/medusa-product-slug-field.tsx
apps/payload/**/*payload*.config.{ts,js}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/adapters.md)
apps/payload/**/*payload*.config.{ts,js}: UsemongooseAdapterfrom '@payloadcms/db-mongodb' for MongoDB database configuration in Payload CMS with DATABASE_URL environment variable
UsepostgresAdapterfrom '@payloadcms/db-postgres' for PostgreSQL configuration with pool.connectionString, setting push to false, and specifying migrationDir
UsesqliteAdapterfrom '@payloadcms/db-sqlite' for SQLite configuration with client.url and enable transactions via transactionOptions property
Uses3Storagefrom '@payloadcms/storage-s3' for AWS S3 file storage configuration with bucket name and AWS credentials from environment variables
Consider available storage adapters:@payloadcms/storage-s3,@payloadcms/storage-azure,@payloadcms/storage-gcs,@payloadcms/storage-r2,@payloadcms/storage-vercel-blob,@payloadcms/storage-uploadthing
UsenodemailerAdapterfrom '@payloadcms/email-nodemailer' for SMTP-based email configuration with defaultFromAddress, defaultFromName, and transportOptions (host, port, auth)
UseresendAdapterfrom '@payloadcms/email-resend' for email configuration via Resend service with apiKey from environment variable
SQLite transactions are disabled by default and must be explicitly enabled via transactionOptions configuration
Files:
apps/payload/src/payload.config.ts
apps/payload/**/payload.config.{ts,js}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/components.md)
apps/payload/**/payload.config.{ts,js}: Define custom components using file paths (not direct imports) in Payload CMS admin config to keep the config lightweight and Node.js compatible
Component paths must be relative to project root or config.admin.importMap.baseDir, with named exports using '#ExportName' suffix or exportName property
Set baseDir in admin.importMap config to establish a custom base directory for resolving component paths in Payload CMS
Use clientProps in component config for serializable custom props and serverProps for non-serializable custom props in Payload CMS
Verify component file paths are correct relative to baseDir and use named export syntax '#ExportName' when needed to resolve component loading issues in Payload CMS
Files:
apps/payload/src/payload.config.ts
apps/payload/**/payload.config.ts
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/payload-overview.md)
apps/payload/**/payload.config.ts: Use storage adapter plugins for cloud storage
UsebuildConfigfrom 'payload' to configure the Payload CMS instance
UsemongooseAdapterfrom '@payloadcms/db-mongodb' for MongoDB database configuration
UselexicalEditorfrom '@payloadcms/richtext-lexical' for rich text editing
Configuretypescript.outputFileto generate payload-types.ts for type safety
Configureadmin.importMap.baseDirin payload config to enable proper component imports
Files:
apps/payload/src/payload.config.ts
apps/payload/**/payload.config.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/AGENTS.md)
apps/payload/**/payload.config.{ts,tsx}: Use file paths (not direct imports) to define components in the Payload config, with proper export suffixes
Enable transactions in SQLite usingtransactionOptions: {}
Files:
apps/payload/src/payload.config.ts
🧠 Learnings (6)
📚 Learning: 2026-07-13T10:43:17.745Z
Learnt from: Luko248
Repo: TechsioCZ/new-engine PR: 510
File: libs/ui/agent-plugin/scripts/pre-push-validate-gate.mjs:0-0
Timestamp: 2026-07-13T10:43:17.745Z
Learning: In Node scripts, treat command strings built with `child_process.execSync(...)` as a potential shell-injection risk when any part of the command comes from untrusted or agent/LLM/remote input (e.g., ref/branch names like `tool_input.command`). Do not interpolate untrusted values into an `execSync` shell command string (and avoid relying on `shellQuote` workarounds). Instead, execute the program directly with argv arrays (e.g., `execFileSync('git', ['rev-parse', ref, ...], { stdio: ... })` or `spawn/execFile` with `args`), passing each argument as a separate array element at every call site so no shell parsing is involved.
Applied to files:
apps/payload/src/app/(payload)/importMap.js
📚 Learning: 2026-02-05T14:43:17.404Z
Learnt from: KaiUweCZE
Repo: NMIT-WR/new-engine PR: 324
File: apps/medusa-be/package.json:0-0
Timestamp: 2026-02-05T14:43:17.404Z
Learning: Validate and enforce React 19 compatibility across monorepo workspaces. Since Medusa UI supports React 19 via root package.json overrides and Medusa Cloud prerequisites show React 19 overrides for npm workspaces, ensure workspace root and all relevant package.json files align with React 19 (18+ requirement is satisfied). When reviewing, verify that overrides exist in the root package.json and that dependent packages in apps or packages directories declare React 19 (or compatible) in their peerDependencies or dependencies as appropriate for workspace usage.
Applied to files:
apps/medusa-be/package.json
📚 Learning: 2026-05-07T19:05:58.339Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 390
File: apps/medusa-be/package.json:78-81
Timestamp: 2026-05-07T19:05:58.339Z
Learning: When reviewing changes to `package.json`, do not automatically flag dependency additions/removals as "manually edited" or as "bypassing the pnpm lockfile" just because the `package.json` diff shows only that file changed. First verify whether `pnpm-lock.yaml` is missing the corresponding entries. Since `pnpm add` updates both `package.json` and `pnpm-lock.yaml` together, legitimate changes can appear in the `package.json` diff while still being properly tracked in the lockfile.
Applied to files:
apps/medusa-be/package.json
📚 Learning: 2026-05-20T15:58:53.048Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 413
File: apps/medusa-be/package.json:77-80
Timestamp: 2026-05-20T15:58:53.048Z
Learning: When reviewing monorepo `package.json` files, treat any dependencies/devDependencies using the `paykit-sdk/*` scope (e.g., `paykit-sdk/core`, `paykit-sdk/stripe`, `paykit-sdk/comgate`, `paykit-sdk/gopay`) as coming from the TechsioCZ/new-engine private npm registry. Do not flag dependency version constraints (e.g., `^1.2.0`) as invalid merely because those packages/versions are not found on the public npm registry. Public-web/private-web availability checks against the public npm API are not applicable for these packages; if validation is needed, rely on the private registry/CI install behavior instead.
Applied to files:
apps/medusa-be/package.json
📚 Learning: 2025-12-16T19:45:17.746Z
Learnt from: BleedingDev
Repo: NMIT-WR/new-engine PR: 207
File: libs/ui/src/molecules/select.tsx:50-50
Timestamp: 2025-12-16T19:45:17.746Z
Learning: When reviewing Tailwind classes in TSX/TS files, prefer using square brackets for arbitrary CSS values and complex expressions. Specifically: - Do not use the parentheses syntax (z-(--z-index)) for anything beyond simple CSS variable references; this syntax auto-wraps in var() and cannot handle calc or complex functions. - Use the square brackets syntax (e.g., h-[calc(var(--available-height)-var(--spacing-content))]) for calc expressions, var with calc, and any complex CSS expressions. This rule applies broadly to Tailwind v4 usage in TSX code across the project.
Applied to files:
apps/payload/src/components/admin/article-slug-field.tsxapps/payload/src/components/admin/medusa-product-slug-field.tsx
📚 Learning: 2026-02-25T14:46:02.729Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 335
File: apps/zane-operator/src/db.ts:205-207
Timestamp: 2026-02-25T14:46:02.729Z
Learning: Enforce PostgreSQL 18+ as the minimum version across docker-compose files. Since the repo uses postgres:18.1-alpine (evidence in docker-compose.yaml), ensure all docker-compose service images for PostgreSQL use 18.1-alpine or newer. When reviewing, look for postgres images with a tag below 18 (e.g., postgres:<older-version>) and update to 18.1-alpine or a newer compatible tag. This guideline applies to all docker-compose YAML files that define PostgreSQL services.
Applied to files:
docker-compose.yaml
🪛 ast-grep (0.44.1)
apps/payload/src/seed.ts
[warning] 201-201: Do not use weak hash functions (MD5/SHA1)
Context: createHash("sha1")
Note: [CWE-328] Use of Weak Hash.
(insecure-hash-typescript)
[warning] 201-201: Avoid SHA1 security protocol
Context: createHash("sha1")
Note: [CWE-327] Use of a Broken or Risky Cryptographic Algorithm (SHA-1).
(avoid-crypto-sha1-typescript)
[warning] 165-165: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(<${tag}(\\s[^>]*)?>([\\s\\S]*?)<\\/${tag}>, "g")
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
[warning] 173-173: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(<${tag}(?:\\s[^>]*)?>([\\s\\S]*?)<\\/${tag}>)
Note: [CWE-1333] Inefficient Regular Expression Complexity
(regexp-from-variable)
apps/payload/src/scripts/import-articles.ts
[warning] 336-336: Avoid SHA1 security protocol
Context: createHash("sha1")
Note: [CWE-327] Use of a Broken or Risky Cryptographic Algorithm (SHA-1).
(avoid-crypto-sha1-typescript)
[warning] 336-336: Do not use weak hash functions (MD5/SHA1)
Context: createHash("sha1")
Note: [CWE-328] Use of Weak Hash.
(insecure-hash-typescript)
🪛 dotenv-linter (4.0.0)
.env.docker
[warning] 97-97: [UnorderedKey] The DC_HERBATICA_BLOG_ARTICLES_XLSX_PATH key should go before the DC_HERBATICA_CATEGORIES_XML_PATH key
(UnorderedKey)
[warning] 100-100: [UnorderedKey] The DC_PAYLOAD_SEED_ARTICLES_OVERWRITE key should go before the DC_PAYLOAD_SEED_ARTICLES_STATUS key
(UnorderedKey)
🔇 Additional comments (17)
.mise.toml (1)
270-270: LGTM!apps/payload/README.md (1)
62-89: LGTM!docker-compose.yaml (1)
245-261: LGTM!docker/development/payload/payload-runtime.sh (1)
28-28: LGTM!apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts (1)
1-17: LGTM!Also applies to: 26-131, 154-233, 241-268, 318-471, 480-653
apps/payload/src/scripts/import-articles.ts (1)
1-296: LGTM!Also applies to: 297-302, 311-343, 376-382, 394-419, 469-493, 511-1050, 1067-1221
apps/payload/src/seed.ts (1)
2-259: LGTM!Also applies to: 275-282, 306-355, 371-556, 561-780
apps/payload/src/components/admin/article-slug-field.tsx (2)
65-116: Extract shared logic withMedusaProductSlugField.See consolidated comment for the cross-file DRY refactor covering this file and
medusa-product-slug-field.tsx.
70-72: VerifypotentiallyStalePathis a validuseFieldoption.See consolidated comment for the cross-file verification covering this file and
medusa-product-slug-field.tsx.apps/payload/src/components/admin/medusa-product-slug-field.tsx (2)
60-109: Extract shared logic withArticleSlugField.See consolidated comment for the cross-file DRY refactor covering this file and
article-slug-field.tsx.
65-67: VerifypotentiallyStalePathis a validuseFieldoption.See consolidated comment for the cross-file verification covering this file and
article-slug-field.tsx.apps/payload/src/app/(payload)/importMap.js (1)
9-11: LGTM!Also applies to: 49-51
apps/payload/src/lib/editors/lexical.ts (1)
4-4: LGTM!Also applies to: 26-27, 58-60
apps/payload/src/lib/blocks/product-carousel.ts (1)
1-32: LGTM!apps/payload/src/payload.config.ts (1)
29-31: LGTM!Also applies to: 83-84
apps/payload/src/payload-types.ts (1)
101-108: LGTM!apps/payload/src/lib/endpoints/article-options.ts (1)
27-34: 🔒 Security & PrivacyAccess control already matches the collection rules
article-optionsis already restricted to authenticated users/admin API-key callers, andarticlesread access isrequireAuth, so this does not bypass collection access control.> Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts (1)
319-325: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winfix(converter): abort when a widget cannot be resolved
The catch retains markup only in
htmlWithCarouselTokens; the cell is still overwritten with converted Lexical content, so the original widget cannot actually be retried. A successful response with no recognised slugs also replaces it with an empty string. Throw or skip the cell whenever resolution produces no carousel.Proposed fix
+ if (replacementParts.length === 0) { + throw new Error("Widget contained no recognised product or article links") + } + output = output.replace(match[0], replacementParts.join("")) } catch (error) { - console.warn( - `Failed to import product widget ${widgetUrl}: ${error instanceof Error ? error.message : String(error)}` - ) - // Keep the original widget markup so the import can be retried later. + throw new Error( + `Failed to import product widget ${widgetUrl}: ${error instanceof Error ? error.message : String(error)}` + ) }Also applies to: 664-684
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts` around lines 319 - 325, Update the widget conversion flow around the catch handling and carousel resolution so unresolved widgets abort or skip replacement of the affected cell instead of writing converted Lexical content. Preserve the original widget markup when resolution fails, including successful responses with no recognized slugs, and only overwrite the cell when a carousel is actually produced; use the surrounding conversion function and its htmlWithCarouselTokens handling to locate both paths.
♻️ Duplicate comments (1)
apps/payload/src/scripts/import-articles.ts (1)
410-426: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy liftfix(import): bind the fetch to the validated DNS result
lookup()validates one resolution, butfetch(currentUrl)resolves the hostname again. An attacker-controlled hostname can use DNS rebinding to return a public address during validation and a private address during connection. Pin the validated address through a custom resolver/dispatcher, or restrict imports to an explicit host allow-list.#!/bin/bash set -euo pipefail file='apps/payload/src/scripts/import-articles.ts' sed -n '383,519p' "$file" rg -n -C3 '"undici"|dispatcher|connect:|lookup:' apps/payload package.json bun.lock 2>/dev/null || trueAlso applies to: 472-487
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/payload/src/scripts/import-articles.ts` around lines 410 - 426, The media import flow around assertSafeMediaUrl and the fetch call must prevent DNS rebinding by connecting to the address validated during lookup. Configure the request with a custom resolver/dispatcher that pins the validated address, or enforce an explicit host allow-list, and apply the same protection to the additional fetch path around the referenced import logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/medusa-be/src/scripts/herbatica-seed.ts`:
- Around line 3530-3552: Update buildPayloadSeedEnv and the
PAYLOAD_SEED_ENV_MAPPINGS loop so mapped variables are copied only when their
source values exist in process.env, rather than calling
getRequiredPayloadSeedEnv for every entry. Preserve omission of undefined
optional values so Payload applies its defaults, while retaining
required-variable validation such as DATABASE_URL through the appropriate native
seed handling.
In `@apps/payload/src/lib/blocks/article-carousel.ts`:
- Around line 11-22: Update the req.payload.find configuration in the article
lookup to include the current req object, preserving the existing query filters
and options so the operation inherits the active transaction, locale, and user
context.
In `@apps/payload/src/lib/endpoints/medusa-products.ts`:
- Around line 48-50: Update resolveFetchSignal so a provided valid AbortSignal
is combined with the 10-second timeout signal via AbortSignal.any() where
supported, ensuring either signal aborts the fetch; retain the timeout-only
fallback for invalid or absent signals and preserve compatibility when
AbortSignal.any() is unavailable.
In `@apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts`:
- Around line 365-369: Update the fallback logic across all listed sites to
preserve empty-value semantics: in
apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts lines 365-369,
explicitly check for a non-empty image alt value before using the fallback; in
apps/payload/src/scripts/import-articles.ts lines 461-464, replace the
unreachable logical-OR default with nullish coalescing; in
apps/payload/src/scripts/import-articles.ts lines 1244-1252, explicitly fall
back when the extracted excerpt is empty; and in apps/payload/src/seed.ts lines
567-570, test the full description before using the short description.
In `@apps/payload/src/scripts/import-articles.ts`:
- Around line 647-676: Update getRichTextPlainText to join block-level sibling
content with a separator so adjacent paragraphs remain distinct in excerpts,
while preserving direct concatenation for inline or adjacent text nodes. Keep
excerptFromContent and decodeRichTextJson behavior unchanged.
- Around line 691-700: Update the unresolved-media error handling after
hydrateRichTextMedia to avoid interpolating complete URLs; transform each
unresolved URL into a redacted path or short stable hash before joining them in
the thrown Error message, while preserving the unresolved count and diagnostic
usefulness.
In `@docker-compose.yaml`:
- Around line 54-60: Add fallback defaults to the PAYLOAD_SEED_ARTICLES_* and
PAYLOAD_SEED_HERBATICA_PRODUCTS_* mappings in the compose environment block,
matching the established fallback values used by their counterparts in
x-payload-env. Preserve the existing DC_ variable references while ensuring
unset variables do not trigger Docker Compose warnings.
---
Outside diff comments:
In `@apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts`:
- Around line 319-325: Update the widget conversion flow around the catch
handling and carousel resolution so unresolved widgets abort or skip replacement
of the affected cell instead of writing converted Lexical content. Preserve the
original widget markup when resolution fails, including successful responses
with no recognized slugs, and only overwrite the cell when a carousel is
actually produced; use the surrounding conversion function and its
htmlWithCarouselTokens handling to locate both paths.
---
Duplicate comments:
In `@apps/payload/src/scripts/import-articles.ts`:
- Around line 410-426: The media import flow around assertSafeMediaUrl and the
fetch call must prevent DNS rebinding by connecting to the address validated
during lookup. Configure the request with a custom resolver/dispatcher that pins
the validated address, or enforce an explicit host allow-list, and apply the
same protection to the additional fetch path around the referenced import logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 312bd97e-689d-4e52-a48d-93e98b1b5195
📒 Files selected for processing (11)
.env.dockerapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/lib/utils/endpoint.tsapps/payload/src/payload.config.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsdocker-compose.yaml
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: Greptile Review
- GitHub Check: main
- GitHub Check: Analyze (javascript-typescript)
⚠️ CI failures not shown inline (1)
GitHub Check: Kilo Code Review: Kilo Code Review failed
Conclusion: failure
Review failed: The message could not be delivered
🧰 Additional context used
📓 Path-based instructions (15)
apps/payload/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/access-control-advanced.md)
apps/payload/**/*.{ts,tsx}: Implement locale-specific access control usingAccessfunction to check user authentication and locale, allowing authenticated users all locales and public users only English content
Implement device-specific access control usingAccessfunction to check user-agent headers, distinguishing between mobile and desktop access
Create IP-based access restriction using factory function that returns anAccessfunction checking x-forwarded-for or x-real-ip headers against allowed IP list
Implement time-based access control to restrict records to today's date range usingAccessfunction with createdAt date comparisons
Create time-based access factory function that returns recent records (last N days) for regular users while granting admins full access
Implement scheduled content access control distinguishing editors/admins who see all content from public users who see only content within publish/unpublish date windows
Implement subscription-based access control using asyncAccessfunction to verify active subscription status, with admin bypass
Create tier-based subscription access factory function that checks subscription tier hierarchy and returns false on inactive subscriptions or errors
Implement role-based access factory functioncreateRoleBasedAccessthat checks if user has any of the specified roles
Implement organization-scoped access factory functioncreateOrgScopedAccessthat restricts documents to user's organization IDs with optional admin bypass
Implement team-based access factory functioncreateTeamBasedAccessthat filters documents by user's team IDs with admin bypass
Implement time-limited access factory functioncreateTimeLimitedAccessthat restricts documents to last N days with admin bypass
Implement public + authenticated collection pattern where create/update/delete are restricted to admins/editors, read shows published content to public and all content to authenticated users
Implement self-service collection...
Files:
apps/payload/src/lib/utils/endpoint.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/payload.config.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts
apps/payload/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/access-control.md)
apps/payload/**/*.{ts,tsx,js,jsx}: Implement the 'admin only' access pattern in Payload CMS by checking if user roles include 'admin' and returning a boolean result
Implement the 'admin or self' access pattern in Payload CMS by checking admin role first, then falling back to self-referential query constraints (e.g.,{ id: { equals: user?.id } })
Implement the 'authenticated or published' access pattern in Payload CMS by returning true for authenticated users and applying query constraints for public access to published documents
In Payload CMS Local API calls, setoverrideAccess: falsewhen passing auserparameter to ensure access control is enforced rather than bypassed
Do NOT rely on the default Local API behavior in Payload CMS, as access control is skipped by default (overrideAccess: true) - always explicitly setoverrideAccess: falsewhen implementing access control
apps/payload/**/*.{ts,tsx,js,jsx}: When performing nested operations in hooks, always passreqparameter to maintain transaction context across all-or-nothing database operations
Passreqtoreq.payload.find()calls within hooks to maintain atomic transaction context across MongoDB, PostgreSQL, and SQLite databases
Passreqtoreq.payload.update()calls within hooks to ensure changes are included in the same transaction and can be rolled back together on errors
Usepayload.db.beginTransaction(),payload.db.commitTransaction(), andpayload.db.rollbackTransaction()for manual transaction control when needed
apps/payload/**/*.{ts,tsx,js,jsx}: Custom endpoints in Payload are not authenticated by default. Always checkreq.userto verify user authentication before processing requests.
Usereq.payloadfor database operations instead of direct database access to ensure access control and hooks execute properly.
Use theaddDataAndFileToRequesthelper from Payload to handle both JSON parsing and file uploads in POST endpoints.
UseheadersWithCorshelper from Payload ...
Files:
apps/payload/src/lib/utils/endpoint.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/payload.config.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts
apps/payload/**/*.{ts,tsx,js,jsx,graphql}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/queries.md)
Use GraphQL queries with proper field selection, filtering (where), limiting (limit), and sorting (sort) when querying Payload CMS via GraphQL
Files:
apps/payload/src/lib/utils/endpoint.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/payload.config.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Import UI components using the
@techsio/ui-kitnamespace, not@libs/ui, for runtime apps
Files:
apps/payload/src/lib/utils/endpoint.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/payload.config.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run Biome linting and formatting only on changed files using 'bunx biome check --write path/to/file'
Files:
apps/payload/src/lib/utils/endpoint.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/payload.config.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts
apps/**/!(medusa-be)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use modern React patterns and React 19 for frontend applications in the monorepo
Files:
apps/payload/src/lib/utils/endpoint.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/article-options.tsapps/payload/src/payload.config.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts
apps/payload/**/endpoints/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/AGENTS.md)
apps/payload/**/endpoints/**/*.{ts,tsx}: Always check authentication in custom endpoints before performing operations
UseAPIErrorfor proper error responses in custom endpoints
Usereq.payloadfor database operations within custom endpoints
Files:
apps/payload/src/lib/endpoints/article-options.tsapps/payload/src/lib/endpoints/medusa-products.ts
apps/payload/**/*payload*.config.{ts,js}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/adapters.md)
apps/payload/**/*payload*.config.{ts,js}: UsemongooseAdapterfrom '@payloadcms/db-mongodb' for MongoDB database configuration in Payload CMS with DATABASE_URL environment variable
UsepostgresAdapterfrom '@payloadcms/db-postgres' for PostgreSQL configuration with pool.connectionString, setting push to false, and specifying migrationDir
UsesqliteAdapterfrom '@payloadcms/db-sqlite' for SQLite configuration with client.url and enable transactions via transactionOptions property
Uses3Storagefrom '@payloadcms/storage-s3' for AWS S3 file storage configuration with bucket name and AWS credentials from environment variables
Consider available storage adapters:@payloadcms/storage-s3,@payloadcms/storage-azure,@payloadcms/storage-gcs,@payloadcms/storage-r2,@payloadcms/storage-vercel-blob,@payloadcms/storage-uploadthing
UsenodemailerAdapterfrom '@payloadcms/email-nodemailer' for SMTP-based email configuration with defaultFromAddress, defaultFromName, and transportOptions (host, port, auth)
UseresendAdapterfrom '@payloadcms/email-resend' for email configuration via Resend service with apiKey from environment variable
SQLite transactions are disabled by default and must be explicitly enabled via transactionOptions configuration
Files:
apps/payload/src/payload.config.ts
apps/payload/**/payload.config.{ts,js}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/components.md)
apps/payload/**/payload.config.{ts,js}: Define custom components using file paths (not direct imports) in Payload CMS admin config to keep the config lightweight and Node.js compatible
Component paths must be relative to project root or config.admin.importMap.baseDir, with named exports using '#ExportName' suffix or exportName property
Set baseDir in admin.importMap config to establish a custom base directory for resolving component paths in Payload CMS
Use clientProps in component config for serializable custom props and serverProps for non-serializable custom props in Payload CMS
Verify component file paths are correct relative to baseDir and use named export syntax '#ExportName' when needed to resolve component loading issues in Payload CMS
Files:
apps/payload/src/payload.config.ts
apps/payload/**/payload.config.ts
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/payload-overview.md)
apps/payload/**/payload.config.ts: Use storage adapter plugins for cloud storage
UsebuildConfigfrom 'payload' to configure the Payload CMS instance
UsemongooseAdapterfrom '@payloadcms/db-mongodb' for MongoDB database configuration
UselexicalEditorfrom '@payloadcms/richtext-lexical' for rich text editing
Configuretypescript.outputFileto generate payload-types.ts for type safety
Configureadmin.importMap.baseDirin payload config to enable proper component imports
Files:
apps/payload/src/payload.config.ts
apps/payload/**/payload.config.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/AGENTS.md)
apps/payload/**/payload.config.{ts,tsx}: Use file paths (not direct imports) to define components in the Payload config, with proper export suffixes
Enable transactions in SQLite usingtransactionOptions: {}
Files:
apps/payload/src/payload.config.ts
apps/medusa-be/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx}: Use TypeScript for type checking - runnpx tsc --noEmitfor validation
Forbidden: Non-null assertions (!) - always use type guards and validation instead
Annotate generic field access with explicitunknowntype before type guards -const v: unknown = result[field]
Don't useas Typewithout validation - always validate before casting
UseModules.*andContainerRegistrationKeys.*constants instead of hardcoding strings
Batch operations with CHUNK_SIZE to avoid unbounded operations
Extract pure functions to separate files for testability without runtime dependencies
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/medusa-be/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx,js,jsx}: Use Biome linter with ultracite preset - runbunx biome check --write .and always use braces in conditionals
Comments should explain 'why', never 'what' - use self-documenting code via clear naming
Always use const per declaration -const a = 1; const b = 2is correct, one variable per line
Use nullish coalescing (??) operator instead of logical OR (||) for default values
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/medusa-be/src/scripts/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/scripts/*.ts: Usemedusa exec ./src/scripts/script-name.ts [args]to run one-off scripts with container access
Scripts receive{ container, args }- parse args manually or use container.resolve() for services
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/medusa-be/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Medusa backend custom logic should be organized in api/, modules/, workflows/, admin/, subscribers/, and jobs/ directories under apps/medusa-be/src/
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
🧠 Learnings (1)
📚 Learning: 2026-02-25T14:46:02.729Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 335
File: apps/zane-operator/src/db.ts:205-207
Timestamp: 2026-02-25T14:46:02.729Z
Learning: Enforce PostgreSQL 18+ as the minimum version across docker-compose files. Since the repo uses postgres:18.1-alpine (evidence in docker-compose.yaml), ensure all docker-compose service images for PostgreSQL use 18.1-alpine or newer. When reviewing, look for postgres images with a tag below 18 (e.g., postgres:<older-version>) and update to 18.1-alpine or a newer compatible tag. This guideline applies to all docker-compose YAML files that define PostgreSQL services.
Applied to files:
docker-compose.yaml
🪛 ast-grep (0.44.1)
apps/medusa-be/src/scripts/herbatica-seed.ts
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
🪛 dotenv-linter (4.0.0)
.env.docker
[warning] 99-99: [UnorderedKey] The DC_PAYLOAD_SEED_ARTICLES_LOCALE key should go before the DC_PAYLOAD_SEED_ARTICLES_XLSX_PATH key
(UnorderedKey)
[warning] 100-100: [UnorderedKey] The DC_PAYLOAD_SEED_ARTICLES_OVERWRITE key should go before the DC_PAYLOAD_SEED_ARTICLES_XLSX_PATH key
(UnorderedKey)
[warning] 101-101: [UnorderedKey] The DC_PAYLOAD_SEED_ARTICLES_SHEET key should go before the DC_PAYLOAD_SEED_ARTICLES_XLSX_PATH key
(UnorderedKey)
[warning] 102-102: [UnorderedKey] The DC_PAYLOAD_SEED_ARTICLES_STATUS key should go before the DC_PAYLOAD_SEED_ARTICLES_XLSX_PATH key
(UnorderedKey)
[warning] 103-103: [UnorderedKey] The DC_PAYLOAD_SEED_ARTICLES_TRANSLATE key should go before the DC_PAYLOAD_SEED_ARTICLES_XLSX_PATH key
(UnorderedKey)
🪛 OpenGrep (1.25.0)
apps/payload/src/scripts/import-articles.ts
[ERROR] 451-451: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.
(coderabbit.command-injection.exec-js)
🔇 Additional comments (8)
apps/payload/src/lib/utils/endpoint.ts (1)
3-64: LGTM!apps/payload/src/lib/endpoints/article-options.ts (1)
34-74: LGTM!apps/payload/src/payload.config.ts (1)
47-51: LGTM!apps/payload/src/seed.ts (3)
264-304: refactor(seed): remove the remaining Payloadnevercasts
where as neveranddata as neverstill bypass generated collection types despite the generic helper. This is the same type-safety concern raised previously.#!/bin/bash set -euo pipefail rg -n -C4 'RequiredDataFromCollectionSlug|Where|where as never|data as never' \ apps/payload/src/seed.ts apps/payload/src/payload-types.tsAs per coding guidelines, “Don't use
as Typewithout validation.”Source: Coding guidelines
365-379: perf(seed): add the remaining id-only projection
depth: 0is now present, but this lookup still retrieves every scalar field although onlyidis consumed. This was already raised in the earlier projection review.As per coding guidelines, use
selectin Payload Local API queries to limit returned fields.Source: Coding guidelines
5-8: LGTM!Also applies to: 253-253
apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts (1)
8-78: LGTM!Also applies to: 244-318, 326-364, 370-410, 491-530, 586-663, 685-726
apps/payload/src/scripts/import-articles.ts (1)
2-59: LGTM!Also applies to: 317-330, 428-460, 465-646, 677-690, 701-740, 1253-1273
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/payload/src/lib/blocks/article-carousel.ts (1)
15-27: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winperf: add
selectparameter to optimise the existence checkHello! To improve query performance and adhere to our coding guidelines, could we please add the
selectoption to this Local API query? Because we are only checking if the article exists, selecting just theidfield will prevent the database from fetching the entire document, which is particularly beneficial for articles containing large amounts of rich text.As per coding guidelines: Use the
selectparameter in Payload Local API queries to limit returned fields and improve query performance.♻️ Proposed refactor
const result = await req.payload.find({ req, collection: "articles", where: { slug: { equals: value.trim(), }, }, depth: 0, limit: 1, pagination: false, overrideAccess: true, + select: { + id: true, + }, })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/payload/src/lib/blocks/article-carousel.ts` around lines 15 - 27, Add a select option to the Payload query in the article existence check, limiting the returned fields to only the article id while preserving the existing slug filter and query behavior.Source: Coding guidelines
apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts (1)
566-589: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winfix(converter): link nodes are still stripped down to bare children.
shouldStripLinkstill returns the flattenedchildrenarray instead ofnextRecord, discarding thelinknode'stype/url/attributes — functionally identical to the behaviour flagged previously (marked "Addressed in commit fabb41a"), just refactored behind a boolean. SinceLinkFeatureis enabled forarticles.content, every hyperlink is still permanently converted to plain text on import.🐛 Proposed fix to preserve link nodes
- const shouldStripLink = record.type === "link" - if (shouldStripLink) { + if (record.type === "link") { addLinkManifestEntry(record, context.linkManifest) } const root = sanitizeLexicalRoot(record, context) if (root !== undefined) { nextRecord.root = root } if (Array.isArray(record.children)) { const children = record.children.flatMap((child) => { const sanitized = sanitizeLexicalNode(child, context) return sanitized === undefined ? [] : sanitized }) - if (shouldStripLink) { - return children.length > 0 ? children : undefined - } - if (children.length === 0 && record.type !== "root") { return } nextRecord.children = children } return nextRecord🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts` around lines 566 - 589, Update the shouldStripLink branch in sanitizeLexicalNode so link records return nextRecord with their sanitized children assigned, rather than returning the flattened children array. Preserve the link node’s type, URL, and other attributes while retaining the existing behavior for links with no children.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@apps/payload/src/lib/blocks/article-carousel.ts`:
- Around line 15-27: Add a select option to the Payload query in the article
existence check, limiting the returned fields to only the article id while
preserving the existing slug filter and query behavior.
In `@apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts`:
- Around line 566-589: Update the shouldStripLink branch in sanitizeLexicalNode
so link records return nextRecord with their sanitized children assigned, rather
than returning the flattened children array. Preserve the link node’s type, URL,
and other attributes while retaining the existing behavior for links with no
children.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 00bac613-e15c-4c4d-82c4-5a9622ac7bbb
📒 Files selected for processing (7)
apps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.tsdocker-compose.yaml
📜 Review details
⚠️ CI failures not shown inline (1)
GitHub Check: Kilo Code Review: Kilo Code Review failed
Conclusion: failure
Review failed: The message could not be delivered
🧰 Additional context used
📓 Path-based instructions (11)
apps/payload/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/access-control-advanced.md)
apps/payload/**/*.{ts,tsx}: Implement locale-specific access control usingAccessfunction to check user authentication and locale, allowing authenticated users all locales and public users only English content
Implement device-specific access control usingAccessfunction to check user-agent headers, distinguishing between mobile and desktop access
Create IP-based access restriction using factory function that returns anAccessfunction checking x-forwarded-for or x-real-ip headers against allowed IP list
Implement time-based access control to restrict records to today's date range usingAccessfunction with createdAt date comparisons
Create time-based access factory function that returns recent records (last N days) for regular users while granting admins full access
Implement scheduled content access control distinguishing editors/admins who see all content from public users who see only content within publish/unpublish date windows
Implement subscription-based access control using asyncAccessfunction to verify active subscription status, with admin bypass
Create tier-based subscription access factory function that checks subscription tier hierarchy and returns false on inactive subscriptions or errors
Implement role-based access factory functioncreateRoleBasedAccessthat checks if user has any of the specified roles
Implement organization-scoped access factory functioncreateOrgScopedAccessthat restricts documents to user's organization IDs with optional admin bypass
Implement team-based access factory functioncreateTeamBasedAccessthat filters documents by user's team IDs with admin bypass
Implement time-limited access factory functioncreateTimeLimitedAccessthat restricts documents to last N days with admin bypass
Implement public + authenticated collection pattern where create/update/delete are restricted to admins/editors, read shows published content to public and all content to authenticated users
Implement self-service collection...
Files:
apps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.ts
apps/payload/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/access-control.md)
apps/payload/**/*.{ts,tsx,js,jsx}: Implement the 'admin only' access pattern in Payload CMS by checking if user roles include 'admin' and returning a boolean result
Implement the 'admin or self' access pattern in Payload CMS by checking admin role first, then falling back to self-referential query constraints (e.g.,{ id: { equals: user?.id } })
Implement the 'authenticated or published' access pattern in Payload CMS by returning true for authenticated users and applying query constraints for public access to published documents
In Payload CMS Local API calls, setoverrideAccess: falsewhen passing auserparameter to ensure access control is enforced rather than bypassed
Do NOT rely on the default Local API behavior in Payload CMS, as access control is skipped by default (overrideAccess: true) - always explicitly setoverrideAccess: falsewhen implementing access control
apps/payload/**/*.{ts,tsx,js,jsx}: When performing nested operations in hooks, always passreqparameter to maintain transaction context across all-or-nothing database operations
Passreqtoreq.payload.find()calls within hooks to maintain atomic transaction context across MongoDB, PostgreSQL, and SQLite databases
Passreqtoreq.payload.update()calls within hooks to ensure changes are included in the same transaction and can be rolled back together on errors
Usepayload.db.beginTransaction(),payload.db.commitTransaction(), andpayload.db.rollbackTransaction()for manual transaction control when needed
apps/payload/**/*.{ts,tsx,js,jsx}: Custom endpoints in Payload are not authenticated by default. Always checkreq.userto verify user authentication before processing requests.
Usereq.payloadfor database operations instead of direct database access to ensure access control and hooks execute properly.
Use theaddDataAndFileToRequesthelper from Payload to handle both JSON parsing and file uploads in POST endpoints.
UseheadersWithCorshelper from Payload ...
Files:
apps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.ts
apps/payload/**/*.{ts,tsx,js,jsx,graphql}
📄 CodeRabbit inference engine (apps/payload/.cursor/rules/queries.md)
Use GraphQL queries with proper field selection, filtering (where), limiting (limit), and sorting (sort) when querying Payload CMS via GraphQL
Files:
apps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.ts
apps/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Import UI components using the
@techsio/ui-kitnamespace, not@libs/ui, for runtime apps
Files:
apps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run Biome linting and formatting only on changed files using 'bunx biome check --write path/to/file'
Files:
apps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.ts
apps/**/!(medusa-be)/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use modern React patterns and React 19 for frontend applications in the monorepo
Files:
apps/payload/src/lib/blocks/article-carousel.tsapps/payload/src/scripts/convert-article-xlsx-html-to-richtext.tsapps/medusa-be/src/scripts/herbatica-seed.tsapps/payload/src/lib/endpoints/medusa-products.tsapps/payload/src/scripts/import-articles.tsapps/payload/src/seed.ts
apps/medusa-be/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx}: Use TypeScript for type checking - runnpx tsc --noEmitfor validation
Forbidden: Non-null assertions (!) - always use type guards and validation instead
Annotate generic field access with explicitunknowntype before type guards -const v: unknown = result[field]
Don't useas Typewithout validation - always validate before casting
UseModules.*andContainerRegistrationKeys.*constants instead of hardcoding strings
Batch operations with CHUNK_SIZE to avoid unbounded operations
Extract pure functions to separate files for testability without runtime dependencies
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/medusa-be/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/**/*.{ts,tsx,js,jsx}: Use Biome linter with ultracite preset - runbunx biome check --write .and always use braces in conditionals
Comments should explain 'why', never 'what' - use self-documenting code via clear naming
Always use const per declaration -const a = 1; const b = 2is correct, one variable per line
Use nullish coalescing (??) operator instead of logical OR (||) for default values
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/medusa-be/src/scripts/*.ts
📄 CodeRabbit inference engine (apps/medusa-be/CLAUDE.md)
apps/medusa-be/src/scripts/*.ts: Usemedusa exec ./src/scripts/script-name.ts [args]to run one-off scripts with container access
Scripts receive{ container, args }- parse args manually or use container.resolve() for services
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/medusa-be/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Medusa backend custom logic should be organized in api/, modules/, workflows/, admin/, subscribers/, and jobs/ directories under apps/medusa-be/src/
Files:
apps/medusa-be/src/scripts/herbatica-seed.ts
apps/payload/**/endpoints/**/*.{ts,tsx}
📄 CodeRabbit inference engine (apps/payload/AGENTS.md)
apps/payload/**/endpoints/**/*.{ts,tsx}: Always check authentication in custom endpoints before performing operations
UseAPIErrorfor proper error responses in custom endpoints
Usereq.payloadfor database operations within custom endpoints
Files:
apps/payload/src/lib/endpoints/medusa-products.ts
🧠 Learnings (1)
📚 Learning: 2026-02-25T14:46:02.729Z
Learnt from: redeyecz
Repo: TechsioCZ/new-engine PR: 335
File: apps/zane-operator/src/db.ts:205-207
Timestamp: 2026-02-25T14:46:02.729Z
Learning: Enforce PostgreSQL 18+ as the minimum version across docker-compose files. Since the repo uses postgres:18.1-alpine (evidence in docker-compose.yaml), ensure all docker-compose service images for PostgreSQL use 18.1-alpine or newer. When reviewing, look for postgres images with a tag below 18 (e.g., postgres:<older-version>) and update to 18.1-alpine or a newer compatible tag. This guideline applies to all docker-compose YAML files that define PostgreSQL services.
Applied to files:
docker-compose.yaml
🪛 ast-grep (0.44.1)
apps/medusa-be/src/scripts/herbatica-seed.ts
[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process-typescript)
🔇 Additional comments (8)
apps/payload/src/lib/endpoints/medusa-products.ts (1)
48-128: LGTM!docker-compose.yaml (1)
52-60: LGTM!apps/medusa-be/src/scripts/herbatica-seed.ts (1)
3537-3540: LGTM!apps/payload/src/scripts/convert-article-xlsx-html-to-richtext.ts (2)
353-381: fix(converter): alt-text fallback now correctly handles empty/whitespace values.Explicit truthy check (
imageAlt ? imageAlt : "...") replaces the earlier unreachable??fallback — nicely done.
534-548: LGTM!apps/payload/src/scripts/import-articles.ts (2)
450-465: LGTM!Also applies to: 682-694, 701-753, 1303-1313
923-935: 🗄️ Data Integrity & IntegrationKeep
skipArticleSlugValidationscoped to the import path. If this flag is only meant to bypass the import-time slug check, wire it to thearticlesvalidation hook rather than making it a general bypass, sincefindExistingBySlugalready controls the update/create branch here.apps/payload/src/seed.ts (1)
567-580: LGTM!
|
Closing this in favor of #547, which already includes all the work from this PR plus the newer blog changes. |
Summary
herbatica-seed.tsseedHerbaticaas a plainmedusa execcommand and keep local backend prepare onmigrateUsage
pnpm --filter @nmit/payload exec payload run src/scripts/convert-article-xlsx-html-to-richtext.ts /var/www/local/seed-files/blog_clanky.xlsx /var/www/local/seed-files/blog_clanky.richtext.xlsxPAYLOAD_SEED_*env points to Payload DB/S3 and richtext XLSX.pnpm --filter medusa-be run seedHerbaticaThis runs the Herbatica Medusa seed and then invokes the Payload seed from the TypeScript seed script. Migrations remain a separate explicit step.
Summary by CodeRabbit