Skip to content

9.0.0-beta.4

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 22 May 07:20
· 135 commits to main since this release
44df737

@comet/admin@9.0.0-beta.4

Minor Changes

  • d7b77af: Add ErrorHandlerProvider and useErrorHandler for centralized error reporting from ErrorBoundary

    ErrorBoundary now invokes an optional onError(error, errorInfo) callback provided through ErrorHandlerProvider's context whenever it catches an error. The visible Alert UI of ErrorBoundary is unchanged — the callback is purely additive and intended for forwarding errors to a reporting service (e.g., Sentry).

    Example

    import { ErrorHandlerProvider } from "@comet/admin";
    
    <ErrorHandlerProvider
        onError={(error, errorInfo) => {
            // Report the error to your error tracking service
            console.error(error, errorInfo.componentStack);
        }}
    >
        {children}
    </ErrorHandlerProvider>;
  • 2fe9d4b: Add support for translating page and document content

    Content translation can now be applied to entire documents at once, in addition to the existing field-level translation.

    Setup

    Wrap the application with AzureAiTranslatorProvider (supports batchTranslate automatically):

    <AzureAiTranslatorProvider enabled showApplyTranslationDialog>
        {children}
    </AzureAiTranslatorProvider>

    Making a document type translatable

    Add createDocumentTranslationMethods and the TranslatableInterface type to the document definition:

    import { createDocumentTranslationMethods, type TranslatableInterface } from "@comet/cms-admin";
    
    const rootBlocks = {
        content: PageContentBlock,
        seo: SeoBlock,
    };
    
    export const Page: DocumentInterface & TranslatableInterface & DependencyInterface = {
        // ...existing config
        ...createDocumentRootBlocksMethods(rootBlocks),
        ...createDocumentTranslationMethods(rootBlocks),
    };

    Adding translate action to the edit page

    createUsePage now returns a translateContent function. Use it with TranslateContentMenuItem inside a CrudMoreActionsMenu:

    const { translateContent /* ...other fields */ } = usePage({ pageId: id });
    
    <CrudMoreActionsMenu overallActions={[<TranslateContentMenuItem translateContent={translateContent} />]} />;

    Page tree integration

    The page tree context menu and bulk action toolbar automatically show a "Translate" action for pages. This translates the page name, slug, and document content.

  • 460cbfb: Add translation support for textarea fields in FinalFormInput

    Previously, only type="text" fields supported content translation. Now type="textarea" fields (used by TextAreaField) also show the translate button and use a multiline translation dialog.

Patch Changes

  • 8e40458: Fix Stack crash when location changes before any breadcrumb is registered

    Stack accessed the last entry of an empty breadcrumb array on location change, causing a TypeError: Cannot set properties of undefined. Guarded the update to skip when no breadcrumbs are registered yet.

@comet/admin-rte@9.0.0-beta.4

Minor Changes

  • 2fe9d4b: Add support for translating page and document content

    Content translation can now be applied to entire documents at once, in addition to the existing field-level translation.

    Setup

    Wrap the application with AzureAiTranslatorProvider (supports batchTranslate automatically):

    <AzureAiTranslatorProvider enabled showApplyTranslationDialog>
        {children}
    </AzureAiTranslatorProvider>

    Making a document type translatable

    Add createDocumentTranslationMethods and the TranslatableInterface type to the document definition:

    import { createDocumentTranslationMethods, type TranslatableInterface } from "@comet/cms-admin";
    
    const rootBlocks = {
        content: PageContentBlock,
        seo: SeoBlock,
    };
    
    export const Page: DocumentInterface & TranslatableInterface & DependencyInterface = {
        // ...existing config
        ...createDocumentRootBlocksMethods(rootBlocks),
        ...createDocumentTranslationMethods(rootBlocks),
    };

    Adding translate action to the edit page

    createUsePage now returns a translateContent function. Use it with TranslateContentMenuItem inside a CrudMoreActionsMenu:

    const { translateContent /* ...other fields */ } = usePage({ pageId: id });
    
    <CrudMoreActionsMenu overallActions={[<TranslateContentMenuItem translateContent={translateContent} />]} />;

    Page tree integration

    The page tree context menu and bulk action toolbar automatically show a "Translate" action for pages. This translates the page name, slug, and document content.

@comet/cms-admin@9.0.0-beta.4

Minor Changes

  • d7b77af: Add onError to CometConfig for centralized error reporting from all error boundaries

    CometConfigProvider now accepts an optional onError(error, errorInfo) callback that is invoked whenever any descendant ErrorBoundary catches an error. Use this to forward errors to a reporting service such as Sentry.

    Example

    <CometConfigProvider
        {...config}
        onError={(error, errorInfo) => {
            // Report the error to your error tracking service
            console.error(error, errorInfo.componentStack);
        }}
    >
        {children}
    </CometConfigProvider>
  • c6703db: Export ChooseDamFilesDialog

    Allows building custom multi-file picker UIs on top of the DAM file dialog (e.g. bulk-adding files to a list block).

    import { ChooseDamFilesDialog } from "@comet/cms-admin";
    
    <ChooseDamFilesDialog open={open} onClose={onClose} onConfirm={(fileIds) => ...} initialFileIds={[]} allowedMimetypes={["image/jpeg"]} />
  • 127a492: Add TipTapRichTextBlock as an alternative to RichTextBlock

  • c6703db: Add multiple prop to FileField for selecting multiple DAM files

    FileField now accepts multiple={true} to select a list of DAM files instead of a single file. Multi-file values are typed as GQLDamFileFieldFileFragment[] (the same fragment used in single-file mode); the component renders a stacked list of files with per-row menu and remove actions. The picker dialog pre-checks the current selection via initialFileIds and returns the picked file ids on confirm. The single-file API is unchanged.

    Example

    <Field name="files" component={FileField} multiple preview={(file) => <Thumbnail fileId={file.id} />} />
  • 2fe9d4b: Add support for translating page and document content

    Content translation can now be applied to entire documents at once, in addition to the existing field-level translation.

    Setup

    Wrap the application with AzureAiTranslatorProvider (supports batchTranslate automatically):

    <AzureAiTranslatorProvider enabled showApplyTranslationDialog>
        {children}
    </AzureAiTranslatorProvider>

    Making a document type translatable

    Add createDocumentTranslationMethods and the TranslatableInterface type to the document definition:

    import { createDocumentTranslationMethods, type TranslatableInterface } from "@comet/cms-admin";
    
    const rootBlocks = {
        content: PageContentBlock,
        seo: SeoBlock,
    };
    
    export const Page: DocumentInterface & TranslatableInterface & DependencyInterface = {
        // ...existing config
        ...createDocumentRootBlocksMethods(rootBlocks),
        ...createDocumentTranslationMethods(rootBlocks),
    };

    Adding translate action to the edit page

    createUsePage now returns a translateContent function. Use it with TranslateContentMenuItem inside a CrudMoreActionsMenu:

    const { translateContent /* ...other fields */ } = usePage({ pageId: id });
    
    <CrudMoreActionsMenu overallActions={[<TranslateContentMenuItem translateContent={translateContent} />]} />;

    Page tree integration

    The page tree context menu and bulk action toolbar automatically show a "Translate" action for pages. This translates the page name, slug, and document content.

Patch Changes

  • fa5c7a4: Fix FileField breaking image block selection

    The DamFileFieldFile fragment lost the image dimensions (width, height, cropArea) needed by DamImageBlock/PixelImageBlock. Selecting an image inside an image block crashed because those fields were missing. Restored them on the fragment.

    Composing the fragment into a parent collection (e.g. a many-to-many to DamFile) exposed a Mikro-ORM gotcha: Collection.loadItems() does not honor eager: true, so each loaded DamFile had an uninitialized image Reference and GraphQL threw Cannot return null for non-nullable field DamFileImage.width. Added an image @ResolveField on FilesResolver that initializes the Reference if needed, so consumers don't have to remember to populate it.

  • 31d9296: Fix duplicate TipTap 'link' extension warning by explicitly disabling StarterKit's built-in Link extension

    StarterKit (v3+) includes @tiptap/extension-link by default. Since we register our own CmsLink mark (also named "link"), this caused a "Duplicate extension names found: ['link']" warning. Setting link: false in StarterKit.configure() resolves this.

  • ae85ba9: Fix TipTapRichTextBlock toolbar colors to match the existing RichTextBlock toolbar

    The TipTap toolbar incorrectly used Comet's greyPalette (where greyPalette[100] is #D9D9D9) for the toolbar background, button icon, hover, and disabled states. This made the toolbar look noticeably darker than the existing Draft.js-based RichTextBlock toolbar, which uses MUI's lighter grey palette (grey[100] is #F5F5F5). The TipTap toolbar now uses the same MUI grey shades for these states so the two toolbars look consistent.

  • ab5e547: Validate the SEO block's structured data field as JSON

    The structured data field in the SEO block now shows a validation error when the entered value is not valid JSON. This matches the existing API-side @IsJSON() validation and prevents invalid payloads from being saved.

@comet/api-generator@9.0.0-beta.4

Patch Changes

  • 16c0e64: Fix missing import for nested ManyToOne resolver target entities

    @comet/api-generator now imports nested ManyToOne target entities in generated resolvers so generated code compiles without unresolved symbol errors.

@comet/cms-api@9.0.0-beta.4

Minor Changes

  • c6703db: Add ids filter to damFilesList

    FileFilterInput now accepts an optional ids: [ID!] to restrict the result set to specific files. Useful for batch-loading a known selection (e.g. after a multi-file picker confirms) in a single request.

  • 127a492: Add TipTapRichTextBlock as an alternative to RichTextBlock

  • 2fe9d4b: Add support for translating page and document content

    Content translation can now be applied to entire documents at once, in addition to the existing field-level translation.

    Setup

    Wrap the application with AzureAiTranslatorProvider (supports batchTranslate automatically):

    <AzureAiTranslatorProvider enabled showApplyTranslationDialog>
        {children}
    </AzureAiTranslatorProvider>

    Making a document type translatable

    Add createDocumentTranslationMethods and the TranslatableInterface type to the document definition:

    import { createDocumentTranslationMethods, type TranslatableInterface } from "@comet/cms-admin";
    
    const rootBlocks = {
        content: PageContentBlock,
        seo: SeoBlock,
    };
    
    export const Page: DocumentInterface & TranslatableInterface & DependencyInterface = {
        // ...existing config
        ...createDocumentRootBlocksMethods(rootBlocks),
        ...createDocumentTranslationMethods(rootBlocks),
    };

    Adding translate action to the edit page

    createUsePage now returns a translateContent function. Use it with TranslateContentMenuItem inside a CrudMoreActionsMenu:

    const { translateContent /* ...other fields */ } = usePage({ pageId: id });
    
    <CrudMoreActionsMenu overallActions={[<TranslateContentMenuItem translateContent={translateContent} />]} />;

    Page tree integration

    The page tree context menu and bulk action toolbar automatically show a "Translate" action for pages. This translates the page name, slug, and document content.

Patch Changes

  • fa5c7a4: Fix FileField breaking image block selection

    The DamFileFieldFile fragment lost the image dimensions (width, height, cropArea) needed by DamImageBlock/PixelImageBlock. Selecting an image inside an image block crashed because those fields were missing. Restored them on the fragment.

    Composing the fragment into a parent collection (e.g. a many-to-many to DamFile) exposed a Mikro-ORM gotcha: Collection.loadItems() does not honor eager: true, so each loaded DamFile had an uninitialized image Reference and GraphQL threw Cannot return null for non-nullable field DamFileImage.width. Added an image @ResolveField on FilesResolver that initializes the Reference if needed, so consumers don't have to remember to populate it.

  • 31d9296: Fix duplicate TipTap 'link' extension warning by explicitly disabling StarterKit's built-in Link extension

    StarterKit (v3+) includes @tiptap/extension-link by default. Since we register our own CmsLink mark (also named "link"), this caused a "Duplicate extension names found: ['link']" warning. Setting link: false in StarterKit.configure() resolves this.

@comet/cli@9.0.0-beta.4

Major Changes

  • 2529907: Replace install-agent-skills with install-agent-features — a combined installer for agent skills and agent rules

    install-agent-features installs skills from skills/<name>/SKILL.md and agentic-plugin/skills/<name>/SKILL.md (folders) and rules from rules/<name>.md (single markdown files) — both from the local repo and from external git repos listed in agent-features.json. Skills install into .agents/skills/ and .claude/skills/; rules install into .agents/rules/, .claude/rules/, .cursor/rules/, and .github/instructions/ so they are picked up by Claude Code, Cursor, GitHub Copilot, and other cloud agents. Rules support the same optional metadata.internal: true frontmatter as skills, and may be organized into subdirectories (the layout is preserved in each target).

    Example agent-features.json:

    {
        "repos": ["https://github.com/vivid-planet/comet.git"]
    }

    Run:

    npx @comet/cli install-agent-features

    Breaking change: the install-agent-skills command and its agent-skills.json config are removed. Migrate by renaming agent-skills.json to agent-features.json (the schema is identical) and replacing the install-agent-skills invocation in package.json and install.sh with install-agent-features.

@comet/eslint-config@9.0.0-beta.4

Major Changes

  • 695a9c9: Promote future/* ESLint rules into the main configs

    The rules previously only available via @comet/eslint-config/future/* are now part of the main configs and apply by default. The future/* subpaths are kept as aliases that re-export the main configs, so existing imports continue to work without changes.

    Newly active rules in the main configs

    • react.js:
      • react/jsx-no-literals (with a small allowlist of common symbols)
      • @typescript-eslint/consistent-type-exports
      • formatjs/enforce-default-message is now enforced as "literal"
    • nextjs.js:
      • node-cache is restricted via no-restricted-imports
    • nestjs.js:
      • node-cache is restricted via no-restricted-imports (and restrictedImportPaths is now exported)

@comet/mail-react@9.0.0-beta.4

Minor Changes

  • 0cc1b06: Add config context with Config, ConfigProvider, and useConfig

    Config is an augmentable interface for runtime configuration — intended for environment-specific data. Add custom keys via TypeScript interface declaration merging:

    declare module "@comet/mail-react" {
        interface Config {
            myKey?: { foo: string };
        }
    }

    Define the config using the config prop on MjmlMailRoot or by mounting ConfigProvider directly. Use the useConfig hook to read the value.

  • ba777cf: Add HtmlPixelImageBlock and MjmlPixelImageBlock for rendering Comet CMS PixelImageBlockData in emails

    Configure MjmlMailRoot.config.pixelImageBlock once with the API's allowed image sizes and base URL; the blocks resolve the render width and build the image URL.

    Pass aspectRatio (e.g. "16x9") to override the DAM crop ratio.

    <MjmlMailRoot
        config={{
            pixelImageBlock: {
                validSizes: [...cometConfig.images.imageSizes, ...cometConfig.images.deviceSizes],
                baseUrl: process.env.API_URL,
            },
        }}
    >
        <MjmlPixelImageBlock data={pixelImageData} width={536} />
    </MjmlMailRoot>
  • a7bb900: Add head and attributes props to MjmlMailRoot

    • headReactNode appended inside <MjmlHead> after the registered styles block.

    • attributesReactNode appended inside <MjmlAttributes> after the default <MjmlAll>.

      <MjmlMailRoot attributes={<MjmlClass name="link" color="blue" />} head={<MjmlFont name="Foo" href="https://example.com/foo.css" />}>
          {/* email body */}
      </MjmlMailRoot>

@comet/site-nextjs@9.0.0-beta.4

Major Changes

  • 8b3932d: Move server-only exports to /server subpath

    Server-only exports have been moved to a separate /server entry point to prevent server-only code from being pulled into client bundles. While tree-shaking previously removed unused server code, this is an optional optimization — Vite's dev server, for example, does not tree-shake, causing errors when importing these packages in non-server environments (e.g., Storybook).

    @comet/site-nextjs: sitePreviewRoute, legacyPagesRouterSitePreviewApiHandler, previewParams, legacyPagesRouterPreviewParams, and persistedQueryRoute must now be imported from @comet/site-nextjs/server:

    - import { sitePreviewRoute } from "@comet/site-nextjs";
    + import { sitePreviewRoute } from "@comet/site-nextjs/server";
    - import { previewParams } from "@comet/site-nextjs";
    + import { previewParams } from "@comet/site-nextjs/server";
    - import { persistedQueryRoute } from "@comet/site-nextjs";
    + import { persistedQueryRoute } from "@comet/site-nextjs/server";

    @comet/site-react: persistedQueryRoute must now be imported from @comet/site-react/server:

    - import { persistedQueryRoute } from "@comet/site-react";
    + import { persistedQueryRoute } from "@comet/site-react/server";

Minor Changes

  • ab5e547: Add JsonLd component for typed schema.org structured data

    Renders any schema-dts entity inside a <script type="application/ld+json"> tag. The payload is escaped so a </script> sequence in user content cannot break out of the script tag.

    import { JsonLd } from "@comet/site-react";
    import type { Organization } from "schema-dts";
    
    <JsonLd<Organization>
        data={{
            "@context": "https://schema.org",
            "@type": "Organization",
            name: "Acme",
            url: "https://acme.example",
            logo: "https://acme.example/logo.png",
        }}
    />;

    Also re-exported from @comet/site-nextjs.

Patch Changes

  • b7daf28: Fix PixelImageBlock and Image failing to render in Next.js Pages Router with Error: Element type is invalid ... but got: object

    @comet/site-nextjs is published as ESM ("type": "module") and the components used a default import of next/image (CJS). Under Next.js Pages Router the server bundler keeps node_modules ESM packages as Node-style externals, which applies Node-style ESM↔CJS interop: import NextImage from "next/image" yields the entire module-namespace object ({ default, getImageProps, __esModule: true }) instead of the component. The default import is now unwrapped at module evaluation time so the components work under both bundler-style and Node-style interop.

@comet/site-react@9.0.0-beta.4

Major Changes

  • 8b3932d: Move server-only exports to /server subpath

    Server-only exports have been moved to a separate /server entry point to prevent server-only code from being pulled into client bundles. While tree-shaking previously removed unused server code, this is an optional optimization — Vite's dev server, for example, does not tree-shake, causing errors when importing these packages in non-server environments (e.g., Storybook).

    @comet/site-nextjs: sitePreviewRoute, legacyPagesRouterSitePreviewApiHandler, previewParams, legacyPagesRouterPreviewParams, and persistedQueryRoute must now be imported from @comet/site-nextjs/server:

    - import { sitePreviewRoute } from "@comet/site-nextjs";
    + import { sitePreviewRoute } from "@comet/site-nextjs/server";
    - import { previewParams } from "@comet/site-nextjs";
    + import { previewParams } from "@comet/site-nextjs/server";
    - import { persistedQueryRoute } from "@comet/site-nextjs";
    + import { persistedQueryRoute } from "@comet/site-nextjs/server";

    @comet/site-react: persistedQueryRoute must now be imported from @comet/site-react/server:

    - import { persistedQueryRoute } from "@comet/site-react";
    + import { persistedQueryRoute } from "@comet/site-react/server";

Minor Changes

  • ab5e547: Add JsonLd component for typed schema.org structured data

    Renders any schema-dts entity inside a <script type="application/ld+json"> tag. The payload is escaped so a </script> sequence in user content cannot break out of the script tag.

    import { JsonLd } from "@comet/site-react";
    import type { Organization } from "schema-dts";
    
    <JsonLd<Organization>
        data={{
            "@context": "https://schema.org",
            "@type": "Organization",
            name: "Acme",
            url: "https://acme.example",
            logo: "https://acme.example/logo.png",
        }}
    />;

    Also re-exported from @comet/site-nextjs.