Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(laboratory): preflight editor components #6498

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

jasonkuhrt
Copy link
Member

@jasonkuhrt jasonkuhrt commented Feb 11, 2025

Follow up from #6476 (review)

closes console-1035

This PR refactors the very large graphiql module into separate concerns. It also tweaks the e2e tests file organization.

Main changes:

  1. Dedicated components for different preflight editors that co-locate concerns about those editors
  2. Dedicated modules for hooks

Minor Changes:

  1. Tweaked various props interfaces
  2. Reduced reliance on useRef
  3. Removed useless cases of useCallback

Copy link
Contributor

coderabbitai bot commented Feb 11, 2025

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Introduced an enhanced preflight modal interface for managing and executing scripts with dedicated editors for code and environment variables.
    • Added visual components that improve the display of editor headers and log messages.
  • Refactor

    • Consolidated and streamlined testing utilities and integration for the GraphiQL interface.
    • Restructured preflight and code editor functionalities for improved maintainability.
  • Chores

    • Updated project configurations and added a new dependency to support advanced code editing features.

Walkthrough

The changes introduce a new namespace, cyLaboratory, which encapsulates functions for managing interactions with a GraphiQL editor within a Cypress testing environment. This includes methods for updating editor values, managing tabs, and handling preflight scripts. Existing test files are refactored to utilize the cyLaboratory namespace, replacing the old laboratory module. Additionally, several new React components, hooks, and type definitions related to preflight functionality are introduced, alongside updates to TypeScript configurations and the addition of a monaco-editor dependency.

Changes

File(s) Change Summary
cypress/e2e/laboratory/_cy.ts, collections.cy.ts, preflight.cy.ts, tabs.cy.ts Introduced and refactored to use the new cyLaboratory namespace and its nested preflight namespace; replaced calls from the old laboratory module with updated methods.
cypress/support/dedent.ts, monaco.ts, testkit.ts, tsconfig.json Added new helper functions (dedent and setMonacoEditorContents), removed legacy laboratory functions and dedent implementation, and updated TS configuration (added monaco-editor type and moduleResolution).
package.json Added monaco-editor dependency (0.52.2) to devDependencies.
packages/web/app/src/lib/MonacoEditorReact/index.ts Imported and exported MonacoEditorReact from @monaco-editor/react for usage in environments like Storybook.
packages/web/app/src/lib/preflight/components/EditorTitle.tsx, EnvironmentEditor.tsx, LogLine.tsx, PreflightModal.tsx, ScriptEditor.tsx, _defaultEditorProps.ts Added several new preflight-related React components and constants to support script and environment editing, log rendering, and modal functionalities.
packages/web/app/src/lib/preflight/graphiql-plugin.tsx Refactored the plugin by removing the old PreflightContent function in favor of a new content function, with updated state management using the new preflight context.
packages/web/app/src/lib/preflight/hooks/usePreflight.tsx, usePreflightContext.ts Introduced a custom hook and context to manage execution of preflight scripts and provide shared preflight data to components.
packages/web/app/src/lib/preflight/index.ts, shared-types.ts Consolidated exports for preflight modules and updated type definitions (e.g., new enum for worker states).
packages/web/app/src/pages/target-laboratory.tsx Updated import paths to reflect the new module re-exports for preflight functionalities.

Sequence Diagram(s)

sequenceDiagram
    participant T as Cypress Test
    participant CL as cyLaboratory
    participant E as CodeMirror Editor

    T->>CL: updateEditorValue("new value")
    CL->>E: Set editor content
    E-->>CL: Confirm update

    T->>CL: getEditorValue()
    CL->>E: Retrieve current value
    E-->>CL: Send value back
Loading
sequenceDiagram
    participant U as User
    participant M as PreflightModal
    participant H as usePreflight Hook
    participant F as Execution Iframe

    U->>M: Input script & environment variables
    M->>H: Submit editor values for execution
    H->>F: Execute the preflight script
    F-->>H: Return logs/results/errors
    H->>M: Update modal state and display outputs
    M->>U: Render feedback in modal
Loading

Possibly related PRs


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

github-actions bot commented Feb 11, 2025

📚 Storybook Deployment

The latest changes are available as preview in: https://a092f61f.hive-storybook.pages.dev

Copy link
Contributor

github-actions bot commented Feb 11, 2025

🐋 This PR was built and pushed to the following Docker images:

Targets: build

Platforms: linux/arm64

Image Tag: 65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c

Docker Bake metadata
{
"app": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/api/health",
          "build-arg:IMAGE_DESCRIPTION": "The app of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/app",
          "build-arg:PORT": "3000",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/app",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/bbr0r89f3h44xgxrxxpu3gq3n",
  "containerimage.config.digest": "sha256:3fee26df63b9cc221728d2ea783218f90b206cfc82e47ba4b00115b90514799b",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:c7482a24efbbb05b5b1e1bb0a7688dfc5f6209c0bac046087c69279d9b3c8c47",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:c7482a24efbbb05b5b1e1bb0a7688dfc5f6209c0bac046087c69279d9b3c8c47",
  "image.name": "ghcr.io/graphql-hive/app:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/app:refactor_laboratory_preflight_modules-arm64"
},
"buildx.build.warnings": [
  {
    "vertex": "sha256:d154a028047cd011f0dee4016aaff1ef34fc7dc89ac6f63fb0b8778394d633c0",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEyKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:d154a028047cd011f0dee4016aaff1ef34fc7dc89ac6f63fb0b8778394d633c0",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTcp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 17
        },
        "end": {
          "line": 17
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTIp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMyk=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 13
        },
        "end": {
          "line": 13
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9ERVNDUklQVElPTicgKGxpbmUgMTQp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 14
        },
        "end": {
          "line": 14
        }
      }
    ]
  },
  {
    "vertex": "sha256:d154a028047cd011f0dee4016aaff1ef34fc7dc89ac6f63fb0b8778394d633c0",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDExKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 11
        },
        "end": {
          "line": 11
        }
      }
    ]
  },
  {
    "vertex": "sha256:d154a028047cd011f0dee4016aaff1ef34fc7dc89ac6f63fb0b8778394d633c0",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAxMik=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 12
        },
        "end": {
          "line": 12
        }
      }
    ]
  },
  {
    "vertex": "sha256:d154a028047cd011f0dee4016aaff1ef34fc7dc89ac6f63fb0b8778394d633c0",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRJTUFHRV9USVRMRScgKGxpbmUgMTUp",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 15
        },
        "end": {
          "line": 15
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIwKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 20
        },
        "end": {
          "line": 20
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIxKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 21
        },
        "end": {
          "line": 21
        }
      }
    ]
  },
  {
    "vertex": "sha256:d154a028047cd011f0dee4016aaff1ef34fc7dc89ac6f63fb0b8778394d633c0",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDEwKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "migrations.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSBjYS1jZXJ0aWZpY2F0ZXMKCldPUktESVIgL3Vzci9zcmMvYXBwCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpFTlYgRU5WSVJPTk1FTlQgcHJvZHVjdGlvbgpFTlYgTk9ERV9FTlYgcHJvZHVjdGlvbgpFTlYgUkVMRUFTRSAkUkVMRUFTRQoKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmxpY2Vuc2VzPU1JVApMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudGl0bGU9JElNQUdFX1RJVExFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS52ZXJzaW9uPSRSRUxFQVNFCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS5kZXNjcmlwdGlvbj0kSU1BR0VfREVTQ1JJUFRJT04KTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmF1dGhvcnM9IlRoZSBHdWlsZCIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlbmRvcj0iS2FtaWwgS2lzaWVsYSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnVybD0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnNvdXJjZT0iaHR0cHM6Ly9naXRodWIuY29tL2dyYXBocWwtaGl2ZS9wbGF0Zm9ybSIKCkVOVFJZUE9JTlQgWyAiL2VudHJ5cG9pbnQuc2giIF0K",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 10
        },
        "end": {
          "line": 10
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRSRUxFQVNFJyAobGluZSAyMSk=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 21
        },
        "end": {
          "line": 21
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "VW5kZWZpbmVkVmFyOiBVc2FnZSBvZiB1bmRlZmluZWQgdmFyaWFibGUgJyRQT1JUJyAobGluZSAyMik=",
    "detail": [
      "VmFyaWFibGVzIHNob3VsZCBiZSBkZWZpbmVkIGJlZm9yZSB0aGVpciB1c2U="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/undefined-var/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 22
        },
        "end": {
          "line": 22
        }
      }
    ]
  },
  {
    "vertex": "sha256:e3182d8dd6287818f20839b0ca486015bfc0dbe5065c6e1266b6b05afe173917",
    "level": 1,
    "short": "TGVnYWN5S2V5VmFsdWVGb3JtYXQ6ICJFTlYga2V5PXZhbHVlIiBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkIG9mIGxlZ2FjeSAiRU5WIGtleSB2YWx1ZSIgZm9ybWF0IChsaW5lIDIyKQ==",
    "detail": [
      "TGVnYWN5IGtleS92YWx1ZSBmb3JtYXQgd2l0aCB3aGl0ZXNwYWNlIHNlcGFyYXRvciBzaG91bGQgbm90IGJlIHVzZWQ="
    ],
    "url": "https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/",
    "sourceInfo": {
      "filename": "services.dockerfile",
      "data": "RlJPTSBub2RlOjIyLjEzLjAtc2xpbQoKUlVOIGFwdC1nZXQgdXBkYXRlICYmIGFwdC1nZXQgaW5zdGFsbCAteSB3Z2V0IGNhLWNlcnRpZmljYXRlcyAmJiBybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyoKCkFSRyBTRVJWSUNFX0RJUl9OQU1FCldPUktESVIgL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FCgpDT1BZIC0tZnJvbT1kaXN0IC4gL3Vzci9zcmMvYXBwLyRTRVJWSUNFX0RJUl9OQU1FLwpDT1BZIC0tZnJvbT1zaGFyZWQgLiAvCgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UubGljZW5zZXM9TUlUCkxBQkVMIG9yZy5vcGVuY29udGFpbmVycy5pbWFnZS50aXRsZT0kSU1BR0VfVElUTEUKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLnZlcnNpb249JFJFTEVBU0UKTEFCRUwgb3JnLm9wZW5jb250YWluZXJzLmltYWdlLmRlc2NyaXB0aW9uPSRJTUFHRV9ERVNDUklQVElPTgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UuYXV0aG9ycz0iVGhlIEd1aWxkIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudmVuZG9yPSJLYW1pbCBLaXNpZWxhIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2UudXJsPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgpMQUJFTCBvcmcub3BlbmNvbnRhaW5lcnMuaW1hZ2Uuc291cmNlPSJodHRwczovL2dpdGh1Yi5jb20vZ3JhcGhxbC1oaXZlL3BsYXRmb3JtIgoKRU5WIEVOVklST05NRU5UIHByb2R1Y3Rpb24KRU5WIFJFTEVBU0UgJFJFTEVBU0UKRU5WIFBPUlQgJFBPUlQKCkhFQUxUSENIRUNLIC0taW50ZXJ2YWw9NXMgXAogIC0tdGltZW91dD01cyBcCiAgLS1zdGFydC1wZXJpb2Q9NXMgXAogIC0tcmV0cmllcz02IFwKICBDTUQgJEhFQUxUSENIRUNLX0NNRAoKRU5UUllQT0lOVCBbICIvZW50cnlwb2ludC5zaCIgXQo=",
      "language": "Dockerfile"
    },
    "range": [
      {
        "start": {
          "line": 22
        },
        "end": {
          "line": 22
        }
      }
    ]
  }
],
"composition-federation-2": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "Federation 2 Composition Service for GraphQL Hive.",
          "build-arg:IMAGE_TITLE": "graphql-hive/composition-federation-2",
          "build-arg:PORT": "3069",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/external-composition",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/xod2de3whgd4qt1ipjglazrnv",
  "containerimage.config.digest": "sha256:4d9034178975b69ff5df72a02c553a0e5e061f5b3fdde264faebcba0c42f6f05",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:23671e1c1e4258c41c93b1025493790c5d3edd4c36895cef5d7a09600401ea3c",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:23671e1c1e4258c41c93b1025493790c5d3edd4c36895cef5d7a09600401ea3c",
  "image.name": "ghcr.io/graphql-hive/composition-federation-2:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/composition-federation-2:refactor_laboratory_preflight_modules-arm64"
},
"emails": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The emails service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/emails",
          "build-arg:PORT": "3006",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/emails",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/vj6s2vc55kkhht1s5ilaezvm6",
  "containerimage.config.digest": "sha256:f059ea02af12c7ee073b4a1384a0687dff032566bddbc7f2ee84159aa829df71",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:41c235a74180c03bc46dcb9494c938d6ef3dc5a40a48fad4968e5078579667db",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:41c235a74180c03bc46dcb9494c938d6ef3dc5a40a48fad4968e5078579667db",
  "image.name": "ghcr.io/graphql-hive/emails:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/emails:refactor_laboratory_preflight_modules-arm64"
},
"policy": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The policy service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/policy",
          "build-arg:PORT": "3012",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/policy",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/e7gdfvctcyf4zes2mee3zdfzn",
  "containerimage.config.digest": "sha256:9ebb18ccb6628b06c530758f38286c23f107d5d29b26a44694ea1bfb35720df6",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:1ac742c471c5ebd2a1247be5d4828e44ddb78ee3b7c7bdb9c9b378350963f4f3",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:1ac742c471c5ebd2a1247be5d4828e44ddb78ee3b7c7bdb9c9b378350963f4f3",
  "image.name": "ghcr.io/graphql-hive/policy:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/policy:refactor_laboratory_preflight_modules-arm64"
},
"rate-limit": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The rate limit service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/rate-limit",
          "build-arg:PORT": "3009",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/rate-limit",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/rsqvwz79e3rcrxmhmhr5libyz",
  "containerimage.config.digest": "sha256:965f0b08fa9458e48307f4357c5e6830c26fb20d45d6d86564f564c1081feaac",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:6376192625cf8bac9e1e1779a0538648b9f99204e396f04fe67816c659e5ace8",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:6376192625cf8bac9e1e1779a0538648b9f99204e396f04fe67816c659e5ace8",
  "image.name": "ghcr.io/graphql-hive/rate-limit:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/rate-limit:refactor_laboratory_preflight_modules-arm64"
},
"schema": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The schema service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/schema",
          "build-arg:PORT": "3002",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/schema",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/8akynflf9fhq1ha6153stx5to",
  "containerimage.config.digest": "sha256:3e8803d4505fecbb32574e4bc4c39405e38269b6cd4294266d6c948dcc7267ce",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:4f20b54af883a0ac4e8d777059f26405a1e9c935c17badd4a9854d690a5db96c",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:4f20b54af883a0ac4e8d777059f26405a1e9c935c17badd4a9854d690a5db96c",
  "image.name": "ghcr.io/graphql-hive/schema:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/schema:refactor_laboratory_preflight_modules-arm64"
},
"server": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The server service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/server",
          "build-arg:PORT": "3001",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/server",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/ikkelsgc3o8pdv3vvivfz31zl",
  "containerimage.config.digest": "sha256:933f9944fbaba74f6e422fd8d96822ccc68855e96ab412b795e73cdef9aa542e",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:fc66bafce15c545293f67dcf08d006f8138acdb690e132d64c4aa82d61694750",
    "size": 2076,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:fc66bafce15c545293f67dcf08d006f8138acdb690e132d64c4aa82d61694750",
  "image.name": "ghcr.io/graphql-hive/server:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/server:refactor_laboratory_preflight_modules-arm64"
},
"storage": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "migrations.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:IMAGE_DESCRIPTION": "The migrations service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/storage",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/ilfouo8mn09e439gbvtpegtbv",
  "containerimage.config.digest": "sha256:dada9ccee79f3835322d54ef3b45cfbb777e3e65e2a5aa99b763b1276b9c6fcb",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:f4019899646bcccb0e028e14709632ecf1a3126cb33b91ff5da265b0ef50ed34",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:f4019899646bcccb0e028e14709632ecf1a3126cb33b91ff5da265b0ef50ed34",
  "image.name": "ghcr.io/graphql-hive/storage:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/storage:refactor_laboratory_preflight_modules-arm64"
},
"stripe-billing": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The stripe billing service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/stripe-billing",
          "build-arg:PORT": "3010",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/stripe-billing",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/7lugk1beh05ipjac5lm6vcb6a",
  "containerimage.config.digest": "sha256:df9fe26cc53720f37be4be912a4c5ae6e2de07796bed3a8226ece58ec5651f5e",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:793c6da995f02d46be0cdccdf2b8a9c47bd7f98a4107b114bf506fbec06a5a42",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:793c6da995f02d46be0cdccdf2b8a9c47bd7f98a4107b114bf506fbec06a5a42",
  "image.name": "ghcr.io/graphql-hive/stripe-billing:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/stripe-billing:refactor_laboratory_preflight_modules-arm64"
},
"tokens": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The tokens service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/tokens",
          "build-arg:PORT": "3003",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/tokens",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/80nnrht2s23vu5hvvh2z385z5",
  "containerimage.config.digest": "sha256:25504e05ee3d485a61cfabb81cbadca0098246cbce025b2facd0369c9ecf6ca4",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:1542a18972521f070af7aa0bbb32691259e9e56a61d3a244db9bdf94ddf9fb46",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:1542a18972521f070af7aa0bbb32691259e9e56a61d3a244db9bdf94ddf9fb46",
  "image.name": "ghcr.io/graphql-hive/tokens:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/tokens:refactor_laboratory_preflight_modules-arm64"
},
"usage": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/usage",
          "build-arg:PORT": "3006",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/usage",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/qpyrffxaqzovpyjfgri6as3vs",
  "containerimage.config.digest": "sha256:ce7f7039045947737fba8e72c4e54f122575fbb65925e350dab64c715d133de4",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:40a82d6304f2219a42134266d40d9827ccd3c2a8aaab99195bc01082e3aaaa05",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:40a82d6304f2219a42134266d40d9827ccd3c2a8aaab99195bc01082e3aaaa05",
  "image.name": "ghcr.io/graphql-hive/usage:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/usage:refactor_laboratory_preflight_modules-arm64"
},
"usage-estimator": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The usage estimator service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/usage-estimator",
          "build-arg:PORT": "3008",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/usage-estimator",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/zv6zjlcea9ytfd8h7bc81256p",
  "containerimage.config.digest": "sha256:192ce249784d9131bf2d78583355b1299dc448a57f062746fc13f57e8bb66d6a",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:824daba5812413ee7a247499ecefaa0b830cf0cf9e7cbb21696b3019dfda1680",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:824daba5812413ee7a247499ecefaa0b830cf0cf9e7cbb21696b3019dfda1680",
  "image.name": "ghcr.io/graphql-hive/usage-estimator:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/usage-estimator:refactor_laboratory_preflight_modules-arm64"
},
"usage-ingestor": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The usage ingestor service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/usage-ingestor",
          "build-arg:PORT": "3007",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/usage-ingestor",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/pau9thb4y1axnt7sqt02mavxb",
  "containerimage.config.digest": "sha256:2372b1a178ae4509f16d92965c0fda523ba470b4285da6c4e0638a720ea357ce",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:580a3f6ba31bc076328efcc6bc873a6bc34b1289dd926e9a14c01eee5d17faea",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:580a3f6ba31bc076328efcc6bc873a6bc34b1289dd926e9a14c01eee5d17faea",
  "image.name": "ghcr.io/graphql-hive/usage-ingestor:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/usage-ingestor:refactor_laboratory_preflight_modules-arm64"
},
"webhooks": {
  "buildx.build.provenance": {
    "buildType": "https://mobyproject.org/buildkit@v1",
    "materials": [
      {
        "uri": "pkg:docker/[email protected]?platform=linux%2Farm64",
        "digest": {
          "sha256": "f5a0871ab03b035c58bdb3007c3d177b001c2145c18e81817b71624dcf7d8bff"
        }
      }
    ],
    "invocation": {
      "configSource": {
        "entryPoint": "services.dockerfile"
      },
      "parameters": {
        "frontend": "dockerfile.v0",
        "args": {
          "build-arg:HEALTHCHECK_CMD": "wget --spider -q http://127.0.0.1:${PORT}/_readiness",
          "build-arg:IMAGE_DESCRIPTION": "The webhooks ingestor service of the GraphQL Hive project.",
          "build-arg:IMAGE_TITLE": "graphql-hive/webhooks",
          "build-arg:PORT": "3005",
          "build-arg:RELEASE": "65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c",
          "build-arg:SERVICE_DIR_NAME": "@hive/webhooks",
          "context:dist": "local:dist",
          "context:shared": "local:shared",
          "frontend.caps": "moby.buildkit.frontend.contexts+forward",
          "local-sessionid:context": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:dockerfile": "uoa69pj82elevo5n96job48iv",
          "local-sessionid:shared": "uoa69pj82elevo5n96job48iv"
        },
        "locals": [
          {
            "name": "context"
          },
          {
            "name": "dist"
          },
          {
            "name": "dockerfile"
          },
          {
            "name": "shared"
          }
        ]
      },
      "environment": {
        "platform": "linux/arm64"
      }
    }
  },
  "buildx.build.ref": "builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f44/builder-b803b07f-72e5-4f94-86c7-df3bfa2f3f440/l3e3uxcocwfau38z66p6re9ms",
  "containerimage.config.digest": "sha256:7961235f54ac36d82a424e8a07cfb643ce506818c174a05b84370d26dee071f2",
  "containerimage.descriptor": {
    "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    "digest": "sha256:0339badfa23d546cfc0457e3d810bab4e28d83975d952e1f2aa363af4bca058d",
    "size": 2075,
    "platform": {
      "architecture": "arm64",
      "os": "linux"
    }
  },
  "containerimage.digest": "sha256:0339badfa23d546cfc0457e3d810bab4e28d83975d952e1f2aa363af4bca058d",
  "image.name": "ghcr.io/graphql-hive/webhooks:65b6fe8e1fbe5fb5e1002d46b1ee924a4216460c-arm64,ghcr.io/graphql-hive/webhooks:refactor_laboratory_preflight_modules-arm64"
}
}

@jasonkuhrt jasonkuhrt marked this pull request as ready for review February 11, 2025 14:48
@jasonkuhrt
Copy link
Member Author

The changes to Cypress could be its own PR. If you prefer that, I'll do it. They were pulled in here from the previous PR #6476

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (12)
packages/web/app/src/lib/preflight/components/EditorTitle.tsx (1)

4-10: Consider accessibility and semantic improvements.

A few suggestions to enhance the component:

  1. Extract the props interface for reusability
  2. Consider using semantic heading elements (h1-h6) based on context
  3. Add ARIA attributes if this acts as a label or heading

Here's a suggested implementation:

+interface EditorTitleProps {
+  children: ReactNode;
+  className?: string;
+  level?: 1 | 2 | 3 | 4 | 5 | 6;
+}
+
-export function EditorTitle(props: { children: ReactNode; className?: string }) {
+export function EditorTitle({ children, className, level = 2 }: EditorTitleProps) {
+  const Component = `h${level}` as const;
   return (
-    <div className={cn('cursor-default text-base font-semibold tracking-tight', props.className)}>
-      {props.children}
-    </div>
+    <Component
+      className={cn('cursor-default text-base font-semibold tracking-tight', className)}
+      aria-level={level}
+    >
+      {children}
+    </Component>
   );
 }
packages/web/app/src/lib/preflight/graphiql-plugin.tsx (1)

20-22: Minor naming suggestion.
The classes.monacoMini key is functional. For clarity, consider a slightly more descriptive name (e.g., monacoEditorMini) to better convey intent.

packages/web/app/src/lib/preflight/hooks/usePreflightContext.ts (1)

1-14: LGTM! Consider adding type safety to the provider.

The implementation follows React context best practices with proper null checks and error messages. However, you could enhance type safety by explicitly typing the provider's value prop.

-export const PreflightProvider = PreflightContext.Provider;
+export const PreflightProvider: React.FC<{
+  value: PreflightObject;
+  children: React.ReactNode;
+}> = PreflightContext.Provider;
packages/web/app/src/lib/preflight/components/EnvironmentEditor.tsx (1)

4-12: LGTM! Consider using a type assertion for better type safety.

The default props are correctly defined and merged. However, you could enhance type safety by using a type assertion to ensure all required props are provided.

-export const defaultProps: Readonly<EditorProps> = {
+export const defaultProps = {
  ...defaultEditorProps,
  defaultLanguage: 'json',
  options: {
    ...defaultEditorProps.options,
    lineNumbers: 'off',
    tabSize: 2,
  },
-};
+} as const satisfies Readonly<EditorProps>;
packages/web/app/src/lib/preflight/components/LogLine.tsx (2)

4-22: LGTM! Consider extracting type guards for better maintainability.

The implementation correctly handles different log types and includes error monitoring. However, the type checking logic could be extracted into separate type guard functions for better maintainability.

+function isSeparator(log: LogRecord): log is { type: 'separator' } {
+  return 'type' in log && log.type === 'separator';
+}

+function isLogMessage(log: LogRecord): log is { level: keyof typeof LOG_COLORS; message: string; line?: number; column?: number } {
+  return 'level' in log && log.level in LOG_COLORS;
+}

 export function LogLine({ log }: { log: LogRecord }) {
-  if ('type' in log && log.type === 'separator') {
+  if (isSeparator(log)) {
     return <hr className="my-2 border-dashed border-current" />;
   }

-  if ('level' in log && log.level in LOG_COLORS) {
+  if (isLogMessage(log)) {
     return (
       <div className={LOG_COLORS[log.level]}>
         {log.level}: {log.message}
         {log.line && log.column ? ` (${log.line}:${log.column})` : ''}
       </div>
     );
   }

24-29: LGTM! Consider using an enum or const assertion for better type safety.

The log colors mapping is correctly defined. However, you could enhance type safety by using an enum or const assertion.

-const LOG_COLORS = {
+const LOG_COLORS = {
  error: 'text-red-400',
  info: 'text-emerald-400',
  warn: 'text-yellow-400',
  log: 'text-gray-400',
-};
+} as const;
cypress/support/monaco.ts (1)

4-20: LGTM! Consider adding retry logic for better test stability.

The implementation correctly handles setting Monaco editor contents. However, since this is used in tests, adding retry logic could improve stability.

 export function setMonacoEditorContents(editorCyName: string, text: string) {
   // wait for textarea appearing which indicates monaco is loaded
   cy.dataCy(editorCyName).find('textarea');
-  cy.window().then((win: Window & typeof globalThis & { monaco: typeof Monaco }) => {
+  cy.window().should(win => {
+    const typedWin = win as Window & typeof globalThis & { monaco: typeof Monaco };
     // First, check if monaco is available on the main window
-    const editor = win.monaco.editor
+    const editor = typedWin.monaco.editor
       .getEditors()
       .find(e => e.getContainerDomNode().parentElement.getAttribute('data-cy') === editorCyName);

     // If Monaco instance is found
     if (editor) {
       editor.setValue(text);
+      return true;
     } else {
-      throw new Error('Monaco editor not found on the window or frames[0]');
+      return false;
     }
-  });
+  }, { timeout: 10000 });
 }
cypress/support/dedent.ts (1)

1-52: Add comprehensive documentation and tests.

While the implementation is solid, consider the following improvements:

  1. Add JSDoc comments describing edge cases and usage examples
  2. Include unit tests to verify behavior with different indentation patterns
  3. Add proper license attribution since the code is from another project
cypress/e2e/laboratory/_cy.ts (2)

52-60: Consider iterative approach for tab management.

The recursive implementation could cause stack overflow with many tabs. Consider using a while loop:

-  export function closeTabsUntilOneLeft() {
-    cy.get('li.graphiql-tab').then($tabs => {
-      if ($tabs.length > 1) {
-        closeActiveTab();
-        // Recurse until there's only one tab left
-        return closeTabsUntilOneLeft();
-      }
-    });
-  }
+  export function closeTabsUntilOneLeft() {
+    cy.get('li.graphiql-tab').then($tabs => {
+      let remainingTabs = $tabs.length;
+      while (remainingTabs > 1) {
+        closeActiveTab();
+        remainingTabs--;
+      }
+    });
+  }

63-80: Consider moving selectors to a separate file.

The selectors object could be moved to a dedicated constants file to improve maintainability and reusability.

packages/web/app/src/lib/preflight/components/PreflightModal.tsx (2)

58-61: Consider using smooth scroll behavior only for larger scroll distances.

The current implementation always uses smooth scrolling, which might feel sluggish for small updates.

Consider this optimization:

-    consoleEl?.scroll({ top: consoleEl.scrollHeight, behavior: 'smooth' });
+    const scrollDistance = consoleEl.scrollHeight - consoleEl.scrollTop;
+    consoleEl?.scroll({
+      top: consoleEl.scrollHeight,
+      behavior: scrollDistance > 100 ? 'smooth' : 'auto'
+    });

75-80: Consider extracting escape key handler to a custom hook.

The escape key handling logic could be reused across other modals.

Consider creating a custom hook:

function usePreventModalClose(condition: (target: EventTarget) => boolean) {
  return (ev: KeyboardEvent) => {
    if (condition(ev.target)) {
      ev.preventDefault();
    }
  };
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5307b0c and ea4dbcb.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (22)
  • cypress/e2e/laboratory/_cy.ts (1 hunks)
  • cypress/e2e/laboratory/collections.cy.ts (9 hunks)
  • cypress/e2e/laboratory/preflight.cy.ts (18 hunks)
  • cypress/e2e/laboratory/tabs.cy.ts (2 hunks)
  • cypress/support/dedent.ts (1 hunks)
  • cypress/support/monaco.ts (1 hunks)
  • cypress/support/testkit.ts (0 hunks)
  • cypress/tsconfig.json (1 hunks)
  • package.json (1 hunks)
  • packages/web/app/src/lib/MonacoEditorReact/index.ts (1 hunks)
  • packages/web/app/src/lib/preflight/components/EditorTitle.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/components/EnvironmentEditor.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/components/LogLine.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/components/PreflightModal.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/components/ScriptEditor.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/components/_defaultEditorProps.ts (1 hunks)
  • packages/web/app/src/lib/preflight/graphiql-plugin.tsx (7 hunks)
  • packages/web/app/src/lib/preflight/hooks/usePreflight.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/hooks/usePreflightContext.ts (1 hunks)
  • packages/web/app/src/lib/preflight/index.ts (1 hunks)
  • packages/web/app/src/lib/preflight/shared-types.ts (1 hunks)
  • packages/web/app/src/pages/target-laboratory.tsx (1 hunks)
💤 Files with no reviewable changes (1)
  • cypress/support/testkit.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/web/app/src/lib/MonacoEditorReact/index.ts
  • packages/web/app/src/lib/preflight/index.ts
  • packages/web/app/src/pages/target-laboratory.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
packages/web/app/src/lib/preflight/shared-types.ts

[error] 6-9: The enum declaration should not be const

Const enums are not supported by bundlers and are incompatible with the 'isolatedModules' mode. Their use can lead to import inexistent values.
See TypeScript Docs for more details.
Safe fix: Turn the const enum into a regular enum.

(lint/suspicious/noConstEnum)

⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: typescript / typecheck
  • GitHub Check: static-analysis / analyze (typescript)
  • GitHub Check: static-analysis / analyze (javascript)
  • GitHub Check: build / dockerize (linux/arm64)
  • GitHub Check: code-style / eslint-and-prettier
  • GitHub Check: build / dockerize (linux/amd64)
  • GitHub Check: alpha / cli-artifacts
  • GitHub Check: SonarCloud
🔇 Additional comments (33)
packages/web/app/src/lib/preflight/components/EditorTitle.tsx (2)

1-2: LGTM! Clean and minimal imports.

The imports are well-organized and specific to the component's needs.


4-10: LGTM! Clean and focused component implementation.

The component is well-structured with good extensibility through className prop and sensible default styles.

packages/web/app/src/lib/preflight/graphiql-plugin.tsx (8)

8-9: Imports appear consistent with existing project structure.
Both the graphql and useToggle imports look valid for their intended usage.


11-11: New icon import is straightforward.
The Pencil1Icon import is properly declared. No issues found.


14-18: Introduced component imports align well with modular approach.
These component imports (EditorTitle, EnvironmentEditor, PreflightModal, ScriptEditor, usePreflightContext) indicate a cleaner design, enhancing maintainability.


40-40: Verified plugin content injection.
Mapping the content property to your new content function is correct and maintains plugin structure.


62-63: New content function integrates hooks for toast and preflight context.
Using useToast and usePreflightContext here is appropriate for cross-cutting concerns like notifications and editor state. The approach appears cohesive and correct.

Also applies to: 65-65


71-72: Consider enforcing validation for environment variables.
While updating environment variables, there's potential for invalid JSON. You might ensure structure correctness or handle parse errors gracefully within this flow.


166-168: Read-only script editor integration is logical.
You correctly pass readOnly options to visually convey an uneditable script while still displaying its content.


193-193: Environment editor addition complements the script editor.
Allowing real-time updates to environment variables helps promote a clear separation of concerns. Implementation appears sound.

packages/web/app/src/lib/preflight/hooks/usePreflight.tsx (12)

1-8: Initial imports and schema references look appropriate.
The combination of react, zod, and your local hooks matches the intended functionality for handling state and validations.


9-22: Type definitions provide clarity.
Defining PreflightResultData, the fragment, and PreflightObject offers a strong foundation for typed interactions.


23-47: Solid foundation for usePreflight initialization.

  • Attaching references to iframeRef and hooking into local storage are sensible.
  • The fallback to an empty string for environment variables is practical.

48-80: Begin execute method with environment variable decoding and early exit.

  • Good approach using JSON parse fallback to an empty object.
  • Early return if preflight is disabled is consistent with a “short-circuit” design.

81-113: Preparing the iframe communication.

  • Generating a random UUID for each run is robust.
  • Event listener setup for message is clear, ensuring the correct postMessage usage.

114-128: Prompt management is well-structured.

  • Opening prompts via promptManager and maintaining IDs in a set ensures concurrency control.
  • Closing prompts if the script finishes early prevents orphan dialogs.

129-190: Handling script result merges environment updates effectively.

  • Merging environment variables and persisting them to local storage fosters a reliable iteration loop.
  • Logging with timestamps is helpful for debugging.

193-214: Error flow captures stack info carefully.

  • Logging the error along with line and column is user-friendly.
  • Closing prompts on error is a nice cleanup step.

216-242: Log messages and no-ops for unrecognized events show defensive coding.

  • Explicit handling of known events plus a safe fallback is good practice.

244-283: Finalizing execution lifecycle.

  • Removal of event listeners and resetting state to ready ensures no leftover side-effects.
  • Graceful fallback if an exception is thrown.

285-295: abortExecution and effect-based cleanup logic.

  • Tying cancellation to a ref, and removing it on unmount, secures the lifecycle.

297-323: Return object is comprehensive.
All necessary states, methods, logs, and references are exposed. This supports flexible integration with the UI.

packages/web/app/src/lib/preflight/components/_defaultEditorProps.ts (1)

1-17: Default editor configurations are concise.

  • The usage of clsx for applying a custom background is flexible.
  • Disabling the minimap and managing scrollbar sizes should enhance readability for short configs.
packages/web/app/src/lib/preflight/components/EnvironmentEditor.tsx (1)

14-25: LGTM! Props spreading and merging is handled correctly.

The component properly merges default props with user-provided props, ensuring proper override behavior.

cypress/e2e/laboratory/tabs.cy.ts (1)

1-35: LGTM! Clean refactor of test utilities.

The changes successfully migrate the test to use the new cyLaboratory namespace while maintaining the same test logic and coverage.

packages/web/app/src/lib/preflight/components/ScriptEditor.tsx (1)

6-29: LGTM! Well-structured editor configuration.

The default props provide comprehensive editor settings and proper TypeScript integration for the lab API.

packages/web/app/src/lib/preflight/shared-types.ts (1)

11-11: LGTM! Clean union type definition.

The LogRecord type union with a separator type provides a clean way to handle different types of log entries.

packages/web/app/src/lib/preflight/components/PreflightModal.tsx (1)

100-126: LGTM! Clean conditional rendering for button states.

The execution button's state management and rendering is well-implemented, with clear visual feedback for running/ready states.

cypress/e2e/laboratory/collections.cy.ts (1)

1-1: LGTM! Consistent usage of cyLaboratory namespace.

The refactoring to use the cyLaboratory namespace is consistent throughout the file, improving maintainability by centralizing laboratory-related functionality.

Also applies to: 19-19, 93-93, 106-106, 130-130, 154-154, 176-176, 182-183, 209-209, 215-216

cypress/e2e/laboratory/preflight.cy.ts (2)

4-6: LGTM! Clean selector organization.

Good practice using a dedicated selectors object and creating a shorthand reference for frequently used namespaces.


23-23: LGTM! Clear test organization.

The test suite is well-organized with descriptive describe blocks that clearly separate different aspects of functionality.

Also applies to: 44-44

cypress/tsconfig.json (1)

5-6: LGTM! TypeScript configuration is properly set up for Monaco editor.

The changes correctly configure TypeScript for Monaco editor integration by:

  1. Setting moduleResolution to "node" which is the recommended setting
  2. Adding monaco-editor to the types array for proper type support
package.json (1)

89-89: Verify Monaco editor version compatibility and security.

The Monaco editor version 0.52.2 is added as a dev dependency. Let's verify if this version is appropriate.

✅ Verification successful

🌐 Web query:

What is the latest version of monaco-editor? Are there any known vulnerabilities in version 0.52.2?

💡 Result:

The latest version of monaco-editor is 0.52.2, released on December 9, 2024[4][8]. This version includes updates such as security fixes for dependencies and general maintenance improvements[4].

Regarding vulnerabilities in version 0.52.2:

  • No direct vulnerabilities are listed in Snyk's database for this specific version[3]
  • A previous security concern (CVE-2024-45801) related to DOMPurify dependencies was resolved before this release[2][6]:
    • The vulnerability involved inefficient regular expression complexity
    • Fixed by updating to DOMPurify v3.1.7 (patched since v3.1.3)[2]
    • Confirmed resolved in monaco-editor v0.52.x through dependency updates[2][6]

Security monitoring platforms like Open Hub show no reported vulnerabilities for monaco-editor versions up to 0.52.2[5]. However, users should always verify dependencies using tools like npm audit or Snyk scans for indirect vulnerabilities[3][8].

Citations:


Monaco Editor Version Verified

  • The latest monaco-editor version is confirmed to be 0.52.2.
  • No known vulnerabilities have been reported for version 0.52.2.

cypress/e2e/laboratory/_cy.ts Show resolved Hide resolved
packages/web/app/src/lib/preflight/shared-types.ts Outdated Show resolved Hide resolved
@jasonkuhrt

This comment was marked as resolved.

@jasonkuhrt jasonkuhrt marked this pull request as draft February 11, 2025 16:20
@jasonkuhrt jasonkuhrt marked this pull request as ready for review February 11, 2025 17:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
packages/web/app/src/lib/preflight/graphiql-plugin.tsx (1)

66-66: Remove debugging console.log.

Remove the commented-out console.log statement as it's no longer needed.

-  // console.log(1, preflight.environmentVariables);
cypress/e2e/laboratory/preflight.cy.ts (2)

23-42: Consider adding more assertions for the regression test.

The regression test at line 25 only verifies that the component loads. Consider adding assertions to verify the component's state and functionality after loading.

 it('regression: loads even if local storage is set to {}', () => {
   window.localStorage.setItem('hive:laboratory:environment', '{}');
   cy.visit(`/${data.slug}/laboratory`);
   cy.get(s.buttonGraphiQLPreflight).click();
+  // Verify component state
+  cy.get(s.buttonGraphiQLPreflight).should('be.visible');
+  cy.get(s.buttonGraphiQLPreflight).should('not.be.disabled');
 });

176-250: Consider extracting repeated selectors into setup.

The header-related tests use similar selectors and setup code. Consider extracting common setup into beforeEach or helper functions to reduce duplication.

 describe('Execution', () => {
+  const setupHeaders = (headers: Record<string, string>) => {
+    cy.dataCy(s.buttonToggleCy).click();
+    cy.dataCy(s.buttonModalCy).click();
+    cyp.setEditorContent(`lab.request.headers.append('${Object.keys(headers)[0]}', '${Object.values(headers)[0]}')`);
+    cy.dataCy(s.modal.buttonSubmitCy).click();
+  };
+
   it('result.request.headers are added to the graphiql request base headers', () => {
     const preflightHeaders = {
       foo: 'bar',
     };
-    cy.dataCy(s.buttonToggleCy).click();
-    cy.dataCy(s.buttonModalCy).click();
-    cyp.setEditorContent(`lab.request.headers.append('foo', '${preflightHeaders.foo}')`);
-    cy.dataCy(s.modal.buttonSubmitCy).click();
+    setupHeaders(preflightHeaders);
     // ...
   });
packages/web/app/src/lib/preflight/components/PreflightModal.tsx (4)

24-46: Extract props interface for better reusability.

Consider extracting the props interface to improve code organization and reusability.

+export interface PreflightModalProps {
+  onSubmit?: (values: PreflightModalEditorValue) => void;
+  isOpen: boolean;
+  toggle: () => void;
+  state: PreflightWorkerState;
+  execute: (script: string) => void;
+  abortExecution: () => void;
+  logs: Array<LogRecord>;
+  clearLogs: () => void;
+  value: PreflightModalEditorValue;
+  onChange?: (value: PreflightModalEditorValue) => void;
+}
+
-export function PreflightModal({
+export function PreflightModal(props: PreflightModalProps) {
+  const {
+    isOpen,
+    toggle,
+    onSubmit,
+    state,
+    execute,
+    abortExecution,
+    logs,
+    clearLogs,
+    value,
+    onChange,
+  } = props;

47-49: Remove prettier-ignore comment by reformatting the line.

The prettier-ignore comment can be removed by breaking the line differently.

-  const [environmentVariablesValue, setEnvironmentVariablesValue] = useState(value.environmentVariables); // prettier-ignore
+  const [environmentVariablesValue, setEnvironmentVariablesValue] = useState(
+    value.environmentVariables
+  );

65-68: Extract console scrolling logic into a custom hook.

Consider extracting the console scrolling logic into a reusable custom hook for better code organization and potential reuse.

+function useAutoScroll(ref: React.RefObject<HTMLElement>, deps: any[]) {
+  useEffect(() => {
+    const el = ref.current;
+    el?.scroll({ top: el.scrollHeight, behavior: 'smooth' });
+  }, deps);
+}
+
 // In component:
-useEffect(() => {
-  const consoleEl = consoleRef.current;
-  consoleEl?.scroll({ top: consoleEl.scrollHeight, behavior: 'smooth' });
-}, [logs]);
+useAutoScroll(consoleRef, [logs]);

81-81: Extract magic numbers into named constants.

Consider extracting hardcoded values into named constants for better maintainability.

+const MODAL_WIDTHS = {
+  default: 'w-11/12',
+  xl: 'w-4/5',
+} as const;
+
+const CONSOLE_STYLES = {
+  background: '#10151f',
+  fontSize: 'text-xs',
+  lineHeight: 'leading-[18px]',
+} as const;
+
-className="w-11/12 max-w-[unset] xl:w-4/5"
+className={`${MODAL_WIDTHS.default} max-w-[unset] xl:${MODAL_WIDTHS.xl}`}

-className="h-1/2 overflow-hidden overflow-y-scroll bg-[#10151f] py-2.5 pl-[26px] pr-2.5 font-mono text-xs/[18px]"
+className={`h-1/2 overflow-hidden overflow-y-scroll bg-[${CONSOLE_STYLES.background}] py-2.5 pl-[26px] pr-2.5 font-mono ${CONSOLE_STYLES.fontSize}/${CONSOLE_STYLES.lineHeight}`}

Also applies to: 169-169

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 657d475 and 65b6fe8.

📒 Files selected for processing (5)
  • cypress/e2e/laboratory/preflight.cy.ts (18 hunks)
  • cypress/support/monaco.ts (1 hunks)
  • packages/web/app/src/lib/preflight/components/PreflightModal.tsx (1 hunks)
  • packages/web/app/src/lib/preflight/graphiql-plugin.tsx (7 hunks)
  • packages/web/app/src/lib/preflight/shared-types.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/web/app/src/lib/preflight/shared-types.ts
  • cypress/support/monaco.ts
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: test / unit
  • GitHub Check: typescript / typecheck
  • GitHub Check: storybook-preview / deployment
  • GitHub Check: static-analysis / analyze (typescript)
  • GitHub Check: static-analysis / analyze (javascript)
  • GitHub Check: build / dockerize (linux/arm64)
  • GitHub Check: build / dockerize (linux/amd64)
  • GitHub Check: alpha / cli-artifacts
  • GitHub Check: code-style / eslint-and-prettier
🔇 Additional comments (10)
packages/web/app/src/lib/preflight/graphiql-plugin.tsx (5)

8-18: LGTM! Well-organized imports and consistent styling.

The imports are logically grouped and the shared Monaco editor styling is properly extracted into a classes object.

Also applies to: 20-22


24-41: LGTM! Clean plugin configuration.

The plugin configuration is concise and follows GraphiQL's plugin API. The SVG icon is accessible with proper stroke attributes.


43-60: LGTM! Well-structured GraphQL mutation.

The mutation is properly defined with comprehensive error handling and type safety.


62-99: LGTM! Clean implementation with good separation of concerns.

The content function effectively manages state and handles updates separately for scripts and environment variables. The error handling is comprehensive and user feedback is provided through toast notifications.


101-208: LGTM! Well-structured UI with good user experience.

The implementation features:

  • Comprehensive modal configuration
  • Properly configured editors with appropriate options
  • Clear visual feedback for disabled state
  • Good accessibility with proper ARIA attributes and data-cy selectors for testing
cypress/e2e/laboratory/preflight.cy.ts (3)

1-7: LGTM! Well-structured module organization.

The refactoring improves maintainability by centralizing selectors and helpers in the cyLaboratory module. The setup is clean and follows best practices.


44-174: LGTM! Comprehensive test coverage with clear scenarios.

The "Preflight Modal" suite effectively tests various scenarios including:

  • Script and environment variable persistence
  • Console output and error handling
  • User prompts and cancellation
  • Environment variable updates
  • Security restrictions

364-452: LGTM! Comprehensive logging tests.

The logging-related tests thoroughly cover:

  • Log visibility states
  • Different log levels
  • Log clearing functionality
  • Error scenarios
packages/web/app/src/lib/preflight/components/PreflightModal.tsx (2)

1-23: LGTM! Well-organized imports and clear type definitions.

The imports are logically grouped, and the PreflightModalEditorValue interface is well-defined with clear properties.


98-199: LGTM! Well-structured layout with proper testing attributes.

The layout is well-organized using CSS Grid, and the testing attributes are properly placed. The button states and icons are handled effectively.

@@ -86,6 +86,7 @@
"graphql": "16.9.0",
"gray-matter": "4.0.3",
"jest-snapshot-serializer-raw": "2.0.0",
"monaco-editor": "0.52.2",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added for static typing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Responding to #6476 (comment)

To have a standard namespace for terms such as Editor and EditorProps. Easy autoimport.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

1 participant