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

feat(server): Add coreSupport to Asset #1246

Merged
merged 6 commits into from
Nov 22, 2024
Merged

Conversation

hexaforce
Copy link
Contributor

@hexaforce hexaforce commented Nov 13, 2024

Overview

We will add a coresupport flag to assets to distinguish them.

What I've done

1. [GetAssets]The asset retrieval query will only return those with coresupport set to true.

	var filter any = bson.M{
		"team": id.String(),
+		"$or": []bson.M{
+			{"coresupport": true},
+			{"coresupport": bson.M{"$exists": false}},
+		},
	}

Note: Data where coresupport is nil will be treated as false.

2. [CreateAsset]Added coresupport to the asset creation mutation.

input CreateAssetInput {
  teamId: ID!
+  coreSupport: Boolean!
  file: Upload!
}

3. When creating a new asset in UploadFileToProperty, coresupport will be set to true.

a, err := uc.Asset.Create(ctx, interfaces.CreateAssetParam{
	WorkspaceID: prj[0].Workspace(),
+	coreSupport:  true,
	File:        gqlmodel.FromFile(&input.File),
}, getOperator(ctx))

What I haven't done

How I tested

Conducted in e2e testing
https://github.com/reearth/reearth-visualizer/blob/feat/exclusion-classic-assets/server/e2e/gql_asset_test.go

Which point I want you to review particularly

Past data is not taken into account. You must update the data directly.

Memo

1. You can retrieve assets by adding CoreFlag to the GET_ASSETS query:

export const GET_ASSETS = gql(`
  query GetAssets($teamId: ID!, $pagination: Pagination, $keyword: String, $sort: AssetSort) {
    assets(teamId: $teamId, pagination: $pagination, keyword: $keyword, sort: $sort) {
      edges {
        cursor
        node {
          ...
+          coreSupport
        }
      }
      nodes {
        ...
+        coreSupport
      }
      ...
    }
  }
`);

2. You need to specify coresupport flag in the CREATE_ASSET mutation:

export const CREATE_ASSET = gql(`
-  mutation CreateAsset($teamId: ID!, $file: Upload!) {
-    createAsset(input: { teamId: $teamId, file: $file }) {
+  mutation CreateAsset($teamId: ID!, $file: Upload!, $coreSupport: Boolean!) {
+    createAsset(input: { teamId: $teamId, file: $file, coreSupport: $coreSupport }) {
      asset {

3. generate graphql

npm run gql

Summary by CodeRabbit

  • New Features

    • Introduced a CoreSupport field for assets, enhancing asset management capabilities.
    • Added end-to-end tests for asset creation and retrieval in the GraphQL API.
  • Bug Fixes

    • Improved asset filtering to include only those with core support.
  • Tests

    • Updated tests to validate the new CoreSupport field in asset creation and retrieval.
  • Documentation

    • Enhanced GraphQL schema documentation with the addition of the CoreSupport field.

Copy link

coderabbitai bot commented Nov 13, 2024

Walkthrough

This pull request introduces a new test file for end-to-end testing of asset management functionalities in a GraphQL API. It adds a coreSupport field to various asset-related structures and modifies several methods to incorporate this new field. The changes include updates to GraphQL queries, resolvers, and data models, ensuring that the API correctly handles asset creation and retrieval based on the coreSupport status.

Changes

File Path Change Summary
server/e2e/gql_asset_test.go Added end-to-end tests for asset creation and retrieval, including new functions and GraphQL queries.
server/gql/asset.graphql Added coreSupport: Boolean! field to Asset and CreateAssetInput types.
server/internal/adapter/gql/generated.go Added CoreSupport field to ComplexityRoot struct and updated GraphQL schema for coreSupport.
server/internal/adapter/gql/gqlmodel/convert_asset.go Updated ToAsset function to include CoreSupport in the returned Asset struct.
server/internal/adapter/gql/gqlmodel/models_gen.go Added CoreSupport field to Asset, CreateAssetInput, Project, and CreateProjectInput structs.
server/internal/adapter/gql/resolver_mutation_asset.go Updated CreateAsset method to include CoreSupport in the CreateAssetParam structure.
server/internal/adapter/gql/resolver_mutation_property.go Modified UploadFileToProperty to include CoreSupport in asset creation.
server/internal/infrastructure/memory/asset.go Updated FindByWorkspace to filter assets based on CoreSupport.
server/internal/infrastructure/mongo/asset.go Modified FindByWorkspace to include coreSupport in MongoDB query filters.
server/internal/infrastructure/mongo/mongodoc/asset.go Added CoreSupport field to AssetDocument struct and updated related methods.
server/internal/usecase/interactor/asset.go Updated Create method to set CoreSupport during asset creation.
server/internal/usecase/interactor/asset_test.go Modified TestAsset_Create to include CoreSupport in asset creation assertions.
server/internal/usecase/interfaces/asset.go Added CoreSupport field to CreateAssetParam struct.
server/pkg/asset/asset.go Introduced coreSupport field and CoreSupport() method to Asset struct.
server/pkg/asset/asset_test.go Updated test to include CoreSupport in expected asset structure.
server/pkg/asset/builder.go Added CoreSupport method to Builder struct for asset construction.

Possibly related PRs

Suggested labels

web

Suggested reviewers

  • pyshx
  • airslice
  • mkumbobeaty

🐇 In the fields where assets grow,
A new support for core we sow.
With tests to check and queries bright,
Our GraphQL shines, a joyful sight!
So hop along, let’s build and play,
For core support is here to stay! 🌟


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.

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

netlify bot commented Nov 13, 2024

Deploy Preview for reearth-web ready!

Name Link
🔨 Latest commit 17e8fd7
🔍 Latest deploy log https://app.netlify.com/sites/reearth-web/deploys/67402db5440c470008c065a7
😎 Deploy Preview https://deploy-preview-1246--reearth-web.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@hexaforce hexaforce changed the title add Visualizer flag feat(server): add Visualizer flag Nov 13, 2024
@hexaforce hexaforce marked this pull request as ready for review November 13, 2024 09:01
@hexaforce hexaforce requested a review from pyshx as a code owner November 13, 2024 09:01
Copy link

@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: 7

🧹 Outside diff range and nitpick comments (16)
server/internal/adapter/gql/generated.go (1)

59847-59847: Consider adding input validation for the visualizer field

While the input handling is implemented correctly, consider adding validation to ensure the visualizer value meets any business rules or constraints.

Example validation could include:

 case "visualizer":
     ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("visualizer"))
     data, err := ec.unmarshalNBoolean2bool(ctx, v)
     if err != nil {
         return it, err
     }
+    // Add any business rule validation here
     it.Visualizer = data

Also applies to: 59861-59867

server/internal/adapter/gql/gqlmodel/convert_asset.go (1)

Line range hint 7-21: Consider adding validation for the visualizer field.

While the mapping is correct, consider if any validation is needed for the visualizer field, especially for backwards compatibility with existing assets as mentioned in the PR objectives.

You might want to:

  1. Add validation logic to handle cases where the visualizer field is not set
  2. Consider documenting the default behavior for existing assets
  3. Add logging for cases where the field is missing to help with monitoring during the transition
server/pkg/asset/asset.go (2)

22-22: Consider adding field documentation and default value implications.

The new visualizer field lacks documentation explaining its purpose and behavior. Additionally, since this affects existing data, we should consider the implications of the default false value for existing records.

Add documentation to clarify the field's purpose:

type Asset struct {
	id          ID
	createdAt   time.Time
	workspace   WorkspaceID
	name        string // file name
	size        int64  // file size
	url         string
	contentType string
-	visualizer  bool
+	visualizer  bool   // determines if the asset should be included in visualization

22-22: Consider data migration strategy and deployment implications.

Since this change affects existing assets and requires manual data updates:

  1. Consider creating a data migration script to set the default visualizer value for existing assets
  2. Plan the deployment to handle the transition period where some assets might not have the visualizer field
  3. Document the default behavior in cases where the visualizer field is not present

Would you like assistance in:

  1. Creating a data migration script?
  2. Documenting the migration strategy?
  3. Implementing graceful handling of missing visualizer fields?
server/gql/asset.graphql (1)

Line range hint 1-72: Schema changes look well-structured

The GraphQL schema changes are clean, consistent, and follow best practices. The new visualizer field is properly integrated into both the Asset type and CreateAssetInput.

Consider documenting the visualizer field's purpose and behavior in the schema using GraphQL descriptions (""" """) to improve schema documentation.

server/internal/adapter/gql/resolver_mutation_asset.go (1)

19-22: Consider documenting data migration requirements.

Since this change affects asset creation and the PR objectives mention that past data needs direct updates, consider adding a code comment about data migration requirements.

Add a comment before the CreateAssetParam struct:

+	// Note: Existing assets without a visualizer flag need to be updated directly in the database.
+	// See migration guide in PR #1246
	res, err := usecases(ctx).Asset.Create(ctx, interfaces.CreateAssetParam{
		WorkspaceID: tid,
		Visualizer:  input.Visualizer,
		File:        gqlmodel.FromFile(&input.File),
	}, getOperator(ctx))
server/internal/usecase/interfaces/asset.go (1)

27-27: Add documentation for the Visualizer field

Consider adding a comment to document:

  • The purpose of the Visualizer flag
  • Whether it's required or optional
  • Any default values or constraints

Example:

type CreateAssetParam struct {
	WorkspaceID accountdomain.WorkspaceID
+	// Visualizer indicates whether the asset should be available for visualization
+	// Default: true for new assets
	Visualizer  bool
	File        *file.File
}
server/pkg/asset/builder.go (2)

Line range hint 14-33: Consider adding visualizer validation in Build method.

The Build() method validates other required fields but doesn't enforce any validation rules for the new visualizer field. According to the PR objectives, this field is required for new assets.

Consider updating the validation:

 func (b *Builder) Build() (*Asset, error) {
   if b.a.id.IsNil() {
     return nil, ErrInvalidID
   }
   if b.a.workspace.IsNil() {
     return nil, ErrEmptyWorkspaceID
   }
   if b.a.url == "" {
     return nil, ErrEmptyURL
   }
   if b.a.size <= 0 {
     return nil, ErrEmptySize
   }
+  // Set default value for visualizer if not explicitly set
+  if !b.a.visualizer {
+    b.a.visualizer = true
+  }
   if b.a.createdAt.IsZero() {
     b.a.createdAt = b.a.CreatedAt()
   }
   return b.a, nil
 }

Line range hint 9-12: Set default visualizer value in New() constructor.

According to the PR objectives, new assets should have visualizer set to true by default. Consider setting this in the constructor.

Update the constructor to set the default value:

 func New() *Builder {
-  return &Builder{a: &Asset{}}
+  return &Builder{a: &Asset{
+    visualizer: true,
+  }}
 }
server/internal/infrastructure/mongo/mongodoc/asset.go (1)

63-63: LGTM: Consider documenting error handling for the Visualizer field

The Visualizer field is correctly mapped in the asset builder chain. Since this is part of the Model() method that can return an error, consider documenting whether any validation rules apply to the Visualizer field that could cause a build error.

server/internal/usecase/interactor/asset_test.go (1)

48-48: Add test cases for different visualizer scenarios

While this test covers the basic case where Visualizer is true, consider adding test cases for:

  • Visualizer: false
  • Omitted Visualizer field (to verify default behavior)

This will ensure complete coverage of the new visualizer functionality.

Here's a suggested test table structure:

tests := []struct {
    name       string
    visualizer *bool
    wantErr    bool
}{
    {
        name:       "with visualizer true",
        visualizer: ptr(true),
        wantErr:    false,
    },
    {
        name:       "with visualizer false",
        visualizer: ptr(false),
        wantErr:    false,
    },
    {
        name:       "without visualizer",
        visualizer: nil,
        wantErr:    false,
    },
}
server/internal/infrastructure/memory/asset.go (1)

Line range hint 89-103: Update TotalSizeByWorkspace to respect visualizer flag

The TotalSizeByWorkspace method should be consistent with FindByWorkspace and only include assets that are visualized.

Apply this change to maintain consistency:

 func (r *Asset) TotalSizeByWorkspace(_ context.Context, wid accountdomain.WorkspaceID) (t int64, err error) {
	if !r.f.CanRead(wid) {
		return 0, nil
	}

	r.data.Range(func(k id.AssetID, v *asset.Asset) bool {
-		if v.Workspace() == wid {
+		if v.Workspace() == wid && (!v.HasVisualizer() || v.Visualizer()) {
			t += v.Size()
		}
		return true
	})
	return
}
server/internal/usecase/interactor/asset.go (2)

Line range hint 38-47: Update FindByWorkspace to filter by visualizer flag.

According to the PR objectives, asset retrieval should return only assets where the visualizer flag is true or doesn't exist. However, the FindByWorkspace method doesn't implement this filtering.

Update the AssetFilter to include visualizer filtering:

 return i.repos.Asset.FindByWorkspace(ctx, tid, repo.AssetFilter{
   Sort:       sort,
   Keyword:    keyword,
   Pagination: p,
+  Visualizer: true, // Include assets where visualizer is true or not set
 })

Line range hint 48-104: Consider documenting data migration strategy.

The PR objectives mention that past data needs manual updates to accommodate the new visualizer flag. Consider adding a comment in the Create method documenting this requirement and any default behavior for existing assets.

Add a comment before the builder chain:

+  // Note: Existing assets without a visualizer flag need manual updates.
+  // New assets default to the specified visualizer value.
   a, err := asset.New().
     NewID().
     Workspace(inp.WorkspaceID).
server/e2e/gql_asset_test.go (1)

143-166: Enhance flexibility of asset retrieval.

The getAssets helper function could be more flexible and robust.

Consider these improvements:

+// GetAssetsOptions contains options for asset retrieval
+type GetAssetsOptions struct {
+    First     int
+    After     string
+    SortField string
+    SortDir   string
+}
+
-func getAssets(e *httpexpect.Expect, teamId string) *httpexpect.Value {
+func getAssets(e *httpexpect.Expect, teamId string, opts *GetAssetsOptions) *httpexpect.Value {
+    if opts == nil {
+        opts = &GetAssetsOptions{
+            First:     20,
+            SortField: "DATE",
+            SortDir:   "DESC",
+        }
+    }
+
     requestBody := GraphQLRequest{
         OperationName: "GetAssets",
         Query:         GetAssetsQuery,
         Variables: map[string]any{
             "teamId": teamId,
             "pagination": map[string]any{
-                "first": 20,
+                "first": opts.First,
+                "after": opts.After,
             },
             "sort": map[string]string{
-                "direction": "DESC",
-                "field":     "DATE",
+                "direction": opts.SortDir,
+                "field":     opts.SortField,
             },
         },
     }
server/internal/adapter/gql/resolver_mutation_property.go (1)

103-103: Consider making the visualizer flag configurable

While setting Visualizer: true aligns with the PR objectives, hardcoding this value might limit future flexibility. Consider:

  1. Making it configurable through the input parameters
  2. Using a configuration value or environment variable for the default setting

Example modification to make it configurable:

-		Visualizer:  true,
+		Visualizer:  input.Visualizer != nil && *input.Visualizer,

This would require updating the UploadFileToPropertyInput struct to include an optional visualizer flag:

type UploadFileToPropertyInput struct {
    // ... existing fields ...
    Visualizer *bool
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3a7abbc and b83942b.

⛔ Files ignored due to path filters (2)
  • server/e2e/test.csv is excluded by !**/*.csv
  • server/e2e/test.png is excluded by !**/*.png
📒 Files selected for processing (16)
  • server/e2e/gql_asset_test.go (1 hunks)
  • server/gql/asset.graphql (3 hunks)
  • server/internal/adapter/gql/generated.go (12 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_asset.go (1 hunks)
  • server/internal/adapter/gql/gqlmodel/models_gen.go (2 hunks)
  • server/internal/adapter/gql/resolver_mutation_asset.go (1 hunks)
  • server/internal/adapter/gql/resolver_mutation_property.go (1 hunks)
  • server/internal/infrastructure/memory/asset.go (1 hunks)
  • server/internal/infrastructure/mongo/asset.go (2 hunks)
  • server/internal/infrastructure/mongo/mongodoc/asset.go (3 hunks)
  • server/internal/usecase/interactor/asset.go (1 hunks)
  • server/internal/usecase/interactor/asset_test.go (2 hunks)
  • server/internal/usecase/interfaces/asset.go (1 hunks)
  • server/pkg/asset/asset.go (2 hunks)
  • server/pkg/asset/asset_test.go (4 hunks)
  • server/pkg/asset/builder.go (1 hunks)
🔇 Additional comments (31)
server/internal/adapter/gql/generated.go (5)

156-156: LGTM: Schema changes align with requirements

The schema changes correctly implement the visualizer flag feature by:

  • Adding a non-nullable visualizer field to the Asset type
  • Including the field in asset creation input
  • Providing proper query filtering options

Also applies to: 8633-8633, 8646-8646, 8683-8695


1985-1991: LGTM: Resolver implementation is robust

The resolver implementation includes:

  • Proper complexity calculation
  • Comprehensive error handling
  • Null checks
  • Correct field resolution

Also applies to: 14680-14722


14829-14830: LGTM: Field context handling is consistent

The visualizer field context is properly integrated across all required locations with consistent error handling.

Also applies to: 15032-15033, 15695-15696


64336-64340: LGTM: Field resolution handles concurrency properly

The field resolution implementation correctly:

  • Follows the concurrent execution pattern
  • Handles null values appropriately

8633-8633: Verify handling of existing assets without visualizer flag

The PR objectives mention that past data needs to be updated directly. Please verify that the resolver properly handles existing assets where the visualizer flag might be missing.

Also applies to: 14680-14709

✅ Verification successful

Let me search for database migration files and visualizer field handling in the codebase.


Let me search for the asset creation and handling code to verify how the visualizer flag is handled.


Let me search for the asset creation implementation to verify how the visualizer flag is handled.


Based on the search results, I can see that:

  1. The Asset model has a visualizer boolean field in both the database schema and GraphQL API
  2. The CreateAssetParam struct includes the visualizer flag
  3. The asset creation mutation accepts the visualizer flag as a parameter
  4. The asset creation implementation properly handles the visualizer flag during asset creation

The code shows that the visualizer flag is a core part of the asset model and is properly handled during creation. There's no need for special handling of missing values since:

  1. The flag is a required boolean field in the GraphQL API
  2. The flag is included in the asset creation parameters
  3. New assets will always have this flag set during creation

The resolver properly handles the visualizer flag for both new and existing assets. No additional validation is needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for null checks or default value handling for the visualizer field

# Check for null handling in asset-related files
rg -A 5 "visualizer.*null|null.*visualizer" 

# Check for default value assignments
rg -A 5 "visualizer.*default|default.*visualizer"

# Check for database migration files
fd -e sql -e js -e ts "migration"

Length of output: 35972


Script:

#!/bin/bash
# Search for database migration files and visualizer field handling
# Look for migrations related to visualizer field
rg -A 5 "visualizer.*migration|migration.*visualizer"

# Look for asset schema definitions and updates
rg -A 10 "type.*Asset|asset.*schema"

# Look for asset creation and update handling
ast-grep --pattern 'func $_(asset|Asset)$_($$$) {
  $$$
}'

Length of output: 110911


Script:

#!/bin/bash
# Search for asset creation and handling code
# Look for asset creation with visualizer flag
ast-grep --pattern 'func $_(Create|New)Asset($$$) {
  $$$
}'

# Look for asset database schema and migrations
rg -A 10 "CREATE TABLE.*asset|ALTER TABLE.*asset"

# Look for asset repository implementation
rg -A 10 "func.*Save.*asset|func.*Create.*asset"

Length of output: 9956


Script:

#!/bin/bash
# Search for asset creation implementation
# Look for the complete asset creation function
rg -A 30 "func.*Create.*ctx.*CreateAssetParam.*operator.*Asset"

# Look for asset model/struct initialization
rg -A 10 "func.*New.*Asset.*\(.*\).*\*?Asset"

# Look for visualizer flag handling in asset
rg -A 5 "visualizer.*=|=.*visualizer"

Length of output: 66336

server/internal/adapter/gql/gqlmodel/convert_asset.go (1)

20-20: LGTM! Verify domain model implementation.

The addition of the Visualizer field mapping looks correct. However, let's verify the implementation of the Visualizer() method in the domain model.

✅ Verification successful

The domain model implementation is verified and correct

The Visualizer() method is properly implemented in the domain model (server/pkg/asset/asset.go) and returns a boolean value from the private visualizer field. The GraphQL model also correctly defines the Visualizer field as a boolean, making the conversion in convert_asset.go valid and type-safe.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the Visualizer() method exists in the asset domain model
# and check its implementation details

# Search for the Visualizer method definition in the asset package
ast-grep --pattern 'func ($_ *Asset) Visualizer() bool {
  $$$
}'

# Look for the Asset struct definition to verify the field
ast-grep --pattern 'type Asset struct {
  $$$
  Visualizer bool
  $$$
}'

Length of output: 1275

server/pkg/asset/asset.go (1)

49-51: LGTM! The getter follows the established pattern.

The Visualizer() method follows the consistent getter pattern used throughout the struct, maintaining good code organization.

Let's verify the consistency of getter methods across the codebase:

✅ Verification successful

Getter methods in Asset struct follow a consistent pattern

The verification confirms that all getter methods in the Asset struct follow the same pattern:

  • Simple method name matching the field name
  • Receiver parameter (a *Asset)
  • Direct return of the corresponding field
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify getter method patterns in the asset package
# Expected: All getter methods should follow the same pattern

ast-grep --pattern 'func (a *Asset) $_() $_ {
  return a.$_
}'

Length of output: 1044

server/gql/asset.graphql (1)

23-23: Verify default value implementation in UploadFileToProperty

The PR objectives mention that UploadFileToProperty should set visualizer to true by default. Let's verify this implementation.

#!/bin/bash
# Description: Look for UploadFileToProperty implementation
# to verify default visualizer value

# Search for the function implementation
ast-grep --pattern 'func $$$UploadFileToProperty$$$'

# Search for any tests verifying this behavior
rg -l "TestUploadFileToProperty" 
server/internal/adapter/gql/resolver_mutation_asset.go (1)

20-20: Verify input validation for the visualizer field.

The implementation correctly passes the visualizer flag to the asset creation parameters. However, we should verify that the input validation is properly handled.

✅ Verification successful

Based on the search results, I can now generate the final response:

Visualizer field validation is properly enforced at the schema level

The GraphQL schema in server/gql/asset.graphql shows that the visualizer field is defined as a non-nullable boolean (Boolean!), which ensures basic type validation. The field is properly integrated into the input type and the GraphQL engine will automatically validate:

  • Required field presence
  • Boolean type validation
  • No additional validation is needed as it's a simple boolean flag
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the CreateAssetInput type has proper validation for the visualizer field

# Look for the CreateAssetInput definition and any validation
ast-grep --pattern 'input CreateAssetInput {
  $$$
  visualizer: $_
  $$$
}'

# Check for any validation middleware or decorators
rg -A 5 'CreateAssetInput.*validate'

Length of output: 117


Script:

#!/bin/bash
# Let's try different approaches to find the input definition and validation

# Search for GraphQL schema files
fd -e graphql -e gql

# Search for CreateAssetInput in any file
rg -A 10 "CreateAssetInput"

# Look for validation related code for assets
rg -A 5 "validate.*Asset|Asset.*validate"

# Search for any visualizer related validation
rg -A 5 "visualizer.*validate|validate.*visualizer"

Length of output: 16601

server/internal/usecase/interfaces/asset.go (2)

27-27: Consider adding validation for the Visualizer field

Since this is a new required field that affects asset filtering, consider:

  1. Adding validation logic in the implementation to ensure the field is properly set
  2. Documenting any business rules around when this should be true/false

Let's check if any validation is implemented in the asset creation flow:

#!/bin/bash
# Description: Check for validation of the Visualizer field in asset creation

# Look for Create method implementations
ast-grep --pattern 'func ($x *$type) Create(ctx context.Context, param CreateAssetParam, op *usecase.Operator) (*asset.Asset, error) {
  $$$
}'

# Look for any validation utilities
rg -g '!generated*' -g '!*_test.go' "func.*[Vv]alidate.*Asset"

27-27: Verify backward compatibility

The PR notes mention that past data needs direct updates. Consider:

  1. Adding a database migration for existing assets
  2. Documenting the default behavior for assets without this flag

Let's check for any migration files:

server/pkg/asset/builder.go (1)

72-75: LGTM! Method implementation follows builder pattern.

The implementation follows the established builder pattern consistently with other methods in the file.

server/internal/infrastructure/mongo/mongodoc/asset.go (3)

20-20: Verify handling of existing documents without the Visualizer field

The addition of the Visualizer field looks good. However, we should ensure proper handling of existing documents in the database that won't have this field.

Consider documenting the default behavior for existing documents and whether any data migration is needed. According to the PR objectives, past data will need direct updates.


41-41: LGTM: Proper initialization of the Visualizer field

The initialization of the Visualizer field from the domain model is implemented correctly and consistently with other fields.


Line range hint 20-63: Verify implementation of visualizer-based filtering

The PR objectives mention that asset retrieval should return assets where "visualizer flag is set to true or does not exist". Let's verify the implementation of this filtering logic.

✅ Verification successful

Visualizer filtering implementation is correct

The MongoDB query in FindByWorkspace correctly implements the requirement to return assets where "visualizer flag is set to true or does not exist" using the $or operator:

"$or": []bson.M{
    {"visualizer": true},
    {"visualizer": bson.M{"$exists": false}},
}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for asset retrieval query implementations
rg -t go "GetAssets|Find.*Asset" --glob "server/**/*.go" -A 5

# Look for MongoDB query filters related to the visualizer field
rg -t go "\$or.*visualizer|find.*visualizer" --glob "server/**/*.go" -A 5

Length of output: 8653


Script:

#!/bin/bash
# Search for MongoDB query filter implementation in the asset repository
rg -t go "filter.*:=.*bson" --glob "server/internal/infrastructure/mongo/asset.go" -A 10

# Search for AssetFilter struct definition
rg -t go "type AssetFilter" --glob "server/**/*.go" -A 5

# Search for visualizer-related MongoDB queries
rg -t go "visualizer.*bson|bson.*visualizer" --glob "server/**/*.go" -A 5

Length of output: 1421


Script:

#!/bin/bash
# Get more context around the visualizer query implementation
rg -t go "visualizer.*bson|bson.*visualizer" --glob "server/internal/infrastructure/mongo/asset.go" -B 10 -A 10

# Look for the complete FindByWorkspace implementation
ast-grep --pattern 'func (r *Asset) FindByWorkspace($$$) {
  $$$
}'

Length of output: 1738

server/pkg/asset/asset_test.go (3)

26-26: LGTM: Visualizer field properly integrated into test structure

The addition of the Visualizer boolean field to the test structure aligns with the PR objectives, and the default value of true correctly implements the requirement for new assets.

Also applies to: 39-39, 48-48


75-75: LGTM: Proper assertion for visualizer field

The assertion correctly validates the visualizer field using the getter method, maintaining proper encapsulation.


Line range hint 1-77: Verify handling of existing assets without visualizer flag

The PR notes that past data needs manual updates. Consider adding a test case that verifies the behavior when an asset doesn't have the visualizer flag set (to ensure backward compatibility).

Let's check if there are any migration tests or handling of null/undefined visualizer flags:

server/internal/usecase/interactor/asset_test.go (2)

70-70: LGTM! Thorough assertion of the visualizer field

The test properly validates both the returned asset and the persisted asset, ensuring the visualizer field is correctly set and stored.


Line range hint 1-85: Verify migration testing coverage

The PR objectives mention that past data needs manual updates for the visualizer flag. Consider adding migration tests to verify how the system handles existing assets without the visualizer field.

Let's check if there are any migration tests:

server/internal/infrastructure/memory/asset.go (2)

52-57: Consider adding error handling for invalid visualizer values

The current implementation assumes the visualizer flag is always valid. Consider adding error handling for cases where the flag might be in an invalid state.

Let's check the error handling patterns in the codebase:

#!/bin/bash
# Description: Check error handling patterns for asset-related operations
# Test: Look for error handling in asset operations
rg -A 5 "return .*, err(or)?" server/internal/infrastructure/memory/

Consider adding validation and error handling:

 func (r *Asset) FindByWorkspace(_ context.Context, wid accountdomain.WorkspaceID, filter repo.AssetFilter) ([]*asset.Asset, *usecasex.PageInfo, error) {
	if !r.f.CanRead(wid) {
		return nil, usecasex.EmptyPageInfo(), nil
	}

+	if err := validateAssetFilter(filter); err != nil {
+		return nil, usecasex.EmptyPageInfo(), fmt.Errorf("invalid filter: %w", err)
+	}
+
	result := r.data.FindAll(func(k id.AssetID, v *asset.Asset) bool {
		return v.Workspace() == wid && v.Visualizer() && (filter.Keyword == nil || strings.Contains(v.Name(), *filter.Keyword))
	})

55-55: ⚠️ Potential issue

Verify handling of existing assets without visualizer flag

The current implementation might hide existing assets that don't have the visualizer flag set. According to the PR objectives, past data needs direct updates.

Let's verify the potential impact:

Consider modifying the condition to handle assets without the visualizer flag as mentioned in the PR objectives:

-return v.Workspace() == wid && v.Visualizer() && (filter.Keyword == nil || strings.Contains(v.Name(), *filter.Keyword))
+return v.Workspace() == wid && (!v.HasVisualizer() || v.Visualizer()) && (filter.Keyword == nil || strings.Contains(v.Name(), *filter.Keyword))
server/internal/usecase/interactor/asset.go (1)

93-93: Verify visualizer flag validation.

The visualizer flag is now included in asset creation, but there's no validation to ensure it meets business requirements.

Let's verify the validation in the related files:

✅ Verification successful

Let me gather more information about any existing validation mechanisms in the codebase.


Let me check for any validation patterns or error handling in the asset-related code.


Based on the gathered information, I can now provide the final response:

The visualizer flag implementation is safe and doesn't require additional validation

The visualizer flag is a simple boolean field in CreateAssetParam that's directly passed to the asset builder. Given its binary nature (true/false) and the straightforward setter implementation in the builder, no additional validation is necessary. The existing error handling in the asset creation flow adequately covers the critical aspects like storage constraints and persistence.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check CreateAssetParam definition and any validation
rg -A 5 "type CreateAssetParam struct" server/internal/usecase/interfaces/
# Check Asset builder's Visualizer method implementation
rg -A 5 "func.*Visualizer" server/pkg/asset/

Length of output: 1104


Script:

#!/bin/bash
# Check for any validation related to assets and visualizer flag
rg -A 5 "func.*Validate.*Asset" server/
# Check for any validation in the asset interactor
rg -A 5 "validate" server/internal/usecase/interactor/asset.go

Length of output: 104


Script:

#!/bin/bash
# Look for error handling or validation patterns in asset creation
ast-grep --pattern 'if err := $$$; err != nil {
  $$$
}'  server/internal/usecase/interactor/asset.go

# Check for any validation or error handling in the builder
rg -B 2 -A 5 "type Builder struct" server/pkg/asset/builder.go

Length of output: 1028

server/e2e/gql_asset_test.go (2)

1-11: LGTM! Clean and well-structured imports.

The imports are appropriate for e2e testing with httpexpect.


1-166: Verify test coverage for visualizer functionality.

Let's ensure we have adequate test coverage for the new visualizer feature.

✅ Verification successful

Test coverage for visualizer functionality is adequate

The visualizer functionality has comprehensive test coverage across multiple layers:

  • Unit tests in asset_test.go verify the visualizer field in the Asset model
  • Integration tests in asset_test.go cover the builder pattern with visualizer
  • E2E tests in gql_asset_test.go validate the GraphQL API behavior
  • Interactor tests in asset_test.go confirm the creation of assets with visualizer flag
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check test coverage for visualizer-related functionality

# Find all test files that might test visualizer functionality
echo "Searching for related test files..."
rg -l "visualizer.*bool" --type go

# Look for visualizer-related functions that might need testing
echo "Checking for untested visualizer-related functions..."
ast-grep --pattern 'func $_($$) {
  $$$
  visualizer
  $$$
}'

Length of output: 381


Script:

#!/bin/bash
# Let's examine the asset-related code more thoroughly

# Check the asset builder implementation
echo "=== Asset Builder Implementation ==="
cat server/pkg/asset/builder.go

# Check the asset model implementation
echo "=== Asset Model Implementation ==="
cat server/pkg/asset/asset.go

# Look for any asset-related test files
echo "=== Other Asset Tests ==="
fd "asset.*test" --type f

Length of output: 2740


Script:

#!/bin/bash
# Let's check the other test files for visualizer coverage

echo "=== Asset Model Tests ==="
cat server/pkg/asset/asset_test.go

echo "=== Asset Interactor Tests ==="
cat server/internal/usecase/interactor/asset_test.go

echo "=== Asset Infrastructure Tests ==="
cat server/internal/infrastructure/mongo/asset_test.go

Length of output: 6524

server/internal/infrastructure/mongo/asset.go (3)

81-83: Good security practice using regexp.QuoteMeta!

The use of QuoteMeta properly escapes regex metacharacters in the search keyword, preventing potential regex injection attacks.


96-97: LGTM! URL filter implementation is correct.

The case-insensitive regex filter using the bucket pattern is appropriate for URL matching.


74-77: LGTM! Visualizer filter implementation looks correct.

The $or condition properly handles both new assets with the visualizer flag and existing assets without it, ensuring backward compatibility.

Let's verify the MongoDB query structure:

✅ Verification successful

Based on the search results, I can now provide a definitive response about the visualizer filter implementation:

The visualizer filter implementation is correct and consistent with the codebase patterns.

The search results show that:

  1. The $or condition pattern is commonly used across the codebase for similar backward compatibility scenarios (e.g., in project.go, property.go, layer.go)
  2. The visualizer field is a well-established concept in the codebase, used in multiple contexts (assets, projects, plugins)
  3. The implementation follows the same pattern used for other optional flags (e.g., deleted field in projects)
  4. The query structure matches MongoDB's recommended approach for handling fields that may or may not exist

The implementation correctly handles both cases:

  • {"visualizer": true} - for assets explicitly marked as visualizer assets
  • {"visualizer": {"$exists": false}} - for legacy assets without the flag
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the MongoDB query structure in other files
# Look for similar query patterns to ensure consistency

rg -U '\$or.*\[.*visualizer' --type go

Length of output: 40


Script:

#!/bin/bash
# Let's try a broader search to understand the usage of visualizer field in MongoDB queries
rg -U 'visualizer.*bson' --type go -A 2 -B 2

# Also search for any other $or conditions to verify query patterns
rg -U '\$or.*bson\.M' --type go -A 2 -B 2

# Let's also check if visualizer is used in other contexts
rg 'visualizer' --type go -A 2 -B 2

Length of output: 71080

server/internal/adapter/gql/resolver_mutation_property.go (1)

102-105: Verify handling of existing assets

The PR notes that "past data will not be considered in this update". Please ensure that:

  1. The UI/API handles cases where the visualizer flag is not set
  2. There's a migration plan or documentation for updating existing assets
server/internal/adapter/gql/gqlmodel/models_gen.go (2)

285-287: ⚠️ Potential issue

Review the CreateAssetInput field ordering and required status

The CreateAssetInput struct has been modified to include the required Visualizer field. Consider:

  1. The field ordering places Visualizer between TeamID and File, which is logical
  2. Making the field optional to maintain backward compatibility with existing clients
  3. Documenting the default value behavior in the GraphQL schema

Let's verify the asset creation mutations and their usage:

✅ Verification successful

Based on the gathered information, I can now provide a final response:

The Visualizer field should be required as implemented

The field ordering and required status are correct for the following reasons:

  1. The implementation in resolver_mutation_asset.go shows that the Visualizer field is directly used in the asset creation process without any default value handling
  2. The field is properly passed through to the usecase layer (interfaces.CreateAssetParam) where it's used to determine the asset type
  3. The field ordering (TeamID, Visualizer, File) is logical as it groups the metadata fields before the content field

There's no need to make the field optional or add default value behavior as:

  • The field appears to be a fundamental property that determines the asset's type
  • No default value handling is implemented in any of the resolvers or business logic
  • The codebase consistently treats this as a required field throughout the asset creation flow
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check asset creation mutations and their usage
# Look for CreateAsset mutation definition
rg "mutation.*CreateAsset.*{" --type graphql

# Look for CreateAssetInput usage in Go code
rg "CreateAssetInput.*struct.*{" --type go

Length of output: 321


Script:

#!/bin/bash
# Look for CreateAsset mutation definition
rg "mutation.*CreateAsset" --type graphql -A 5

# Look for CreateAssetInput usage in Go code
rg "type CreateAssetInput" --type go -A 5

# Check GraphQL schema for asset creation
fd "schema.graphql" --exec cat {}

# Look for asset creation handler implementation
rg "func.*CreateAsset" --type go -A 10

Length of output: 10093


Script:

#!/bin/bash
# Search for schema.gql or schema.graphqls files
fd "\.(gql|graphqls)$" --exec cat {}

# Look for the default value handling of Visualizer in the resolver
rg "Visualizer.*=.*" --type go -A 2

# Check for any existing asset creation tests that might show the expected behavior
rg "TestCreateAsset" --type go -A 10

Length of output: 3771


226-226: ⚠️ Potential issue

Consider the impact of adding a required boolean field

The addition of Visualizer bool to the Asset struct is a breaking change. According to the PR objectives, past data will not have this field set. Consider:

  1. Making the field optional (*bool) to handle existing assets
  2. Documenting the default behavior for existing assets
  3. Adding a data migration plan

Let's verify the GraphQL schema and queries that use this field:

server/gql/asset.graphql Show resolved Hide resolved
server/gql/asset.graphql Outdated Show resolved Hide resolved
server/pkg/asset/builder.go Outdated Show resolved Hide resolved
server/pkg/asset/asset_test.go Outdated Show resolved Hide resolved
server/e2e/gql_asset_test.go Outdated Show resolved Hide resolved
server/internal/infrastructure/mongo/asset.go Outdated Show resolved Hide resolved
@hexaforce hexaforce force-pushed the feat/exclusion-classic-assets branch 2 times, most recently from d07debd to 948e16f Compare November 21, 2024 01:17
Copy link

@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

🧹 Outside diff range and nitpick comments (1)
server/internal/infrastructure/mongo/asset.go (1)

74-77: Consider improving documentation and configurability of the visualizer filter.

While the implementation correctly filters assets based on the visualizer flag, consider these improvements:

  1. Add comments explaining the visualizer flag's purpose and behavior
  2. Consider making the default visualizer behavior configurable through environment variables
+// Default visualizer filter configuration
+const defaultVisualizerEnabled = true

 var filter any = bson.M{
     "team": id.String(),
     "$or": []bson.M{
+        // Return assets where visualizer is explicitly enabled or implicitly enabled (field doesn't exist)
+        // This maintains backward compatibility with existing assets while supporting the new visualizer feature
         {"visualizer": true},
         {"visualizer": bson.M{"$exists": false}},
     },
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d07debd and 948e16f.

⛔ Files ignored due to path filters (2)
  • server/e2e/test.csv is excluded by !**/*.csv
  • server/e2e/test.png is excluded by !**/*.png
📒 Files selected for processing (16)
  • server/e2e/gql_asset_test.go (1 hunks)
  • server/gql/asset.graphql (3 hunks)
  • server/internal/adapter/gql/generated.go (12 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_asset.go (1 hunks)
  • server/internal/adapter/gql/gqlmodel/models_gen.go (2 hunks)
  • server/internal/adapter/gql/resolver_mutation_asset.go (1 hunks)
  • server/internal/adapter/gql/resolver_mutation_property.go (1 hunks)
  • server/internal/infrastructure/memory/asset.go (1 hunks)
  • server/internal/infrastructure/mongo/asset.go (2 hunks)
  • server/internal/infrastructure/mongo/mongodoc/asset.go (3 hunks)
  • server/internal/usecase/interactor/asset.go (1 hunks)
  • server/internal/usecase/interactor/asset_test.go (2 hunks)
  • server/internal/usecase/interfaces/asset.go (1 hunks)
  • server/pkg/asset/asset.go (2 hunks)
  • server/pkg/asset/asset_test.go (4 hunks)
  • server/pkg/asset/builder.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (15)
  • server/e2e/gql_asset_test.go
  • server/gql/asset.graphql
  • server/internal/adapter/gql/generated.go
  • server/internal/adapter/gql/gqlmodel/convert_asset.go
  • server/internal/adapter/gql/gqlmodel/models_gen.go
  • server/internal/adapter/gql/resolver_mutation_asset.go
  • server/internal/adapter/gql/resolver_mutation_property.go
  • server/internal/infrastructure/memory/asset.go
  • server/internal/infrastructure/mongo/mongodoc/asset.go
  • server/internal/usecase/interactor/asset.go
  • server/internal/usecase/interactor/asset_test.go
  • server/internal/usecase/interfaces/asset.go
  • server/pkg/asset/asset.go
  • server/pkg/asset/asset_test.go
  • server/pkg/asset/builder.go
🔇 Additional comments (2)
server/internal/infrastructure/mongo/asset.go (2)

88-90: The previous review comment about refactoring the bucket pattern logic is still applicable.

The suggestions from the previous review about:

  • Converting magic strings to constants
  • Using environment variables for test configuration
  • Simplifying the conditional flow

are still relevant to this code segment.


74-77: Verify index coverage for the visualizer filter.

The new $or condition on the visualizer field might benefit from an index to optimize query performance, especially for large collections.

Let's check the existing indexes and their coverage:

Consider adding an index if query performance is a concern:

 var (
-    assetIndexes       = []string{"team"}
+    assetIndexes       = []string{"team", "visualizer"}
     assetUniqueIndexes = []string{"id"}
 )
✅ Verification successful

No index needed for the visualizer field

Based on the codebase analysis, the visualizer field in the asset collection does not require a dedicated index for the following reasons:

  1. The existing index coverage is sufficient:
assetIndexes = []string{"team"}
  1. The $or query on visualizer field is used in combination with a simple equality match, which is not a performance-critical operation since:
  • The condition is simple (true or non-existent)
  • The field has low cardinality (boolean/null values)
  • The query is likely not frequently executed

Adding an index would:

  • Increase storage overhead
  • Impact write performance
  • Provide minimal query performance benefit given the nature of the field and query pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check existing indexes and their coverage for the visualizer field

# Check if visualizer field is covered by any existing indexes
ast-grep --pattern 'assetIndexes = []string{$$$}'

# Check if there are any explain plan hints about index usage
ast-grep --pattern 'client.Find($$$explain$$$)'

Length of output: 101


Script:

#!/bin/bash
# Let's try a broader search for index definitions and mongo queries

# Search for index-related code
rg -i "index|indexes" --type go -A 5 -B 5

# Search for mongo collection setup and configuration
rg "mongo" --type go -A 5 -B 5

# Search specifically for asset collection setup
rg "asset.*collection" --type go -i -A 5 -B 5

Length of output: 150570

@hexaforce hexaforce force-pushed the feat/exclusion-classic-assets branch from acacab6 to 6f0ea74 Compare November 21, 2024 05:38
Copy link

@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: 8

🧹 Outside diff range and nitpick comments (29)
server/internal/usecase/interfaces/published.go (1)

40-40: LGTM! Consider adding unit tests.

The mapping between the interface method and struct field is correct. Consider adding unit tests to verify the behavior with both true and false values for the core flag.

Would you like me to help generate unit tests for the PublishedMetadataFrom function?

server/internal/infrastructure/mongo/mongodoc/asset.go (1)

Line range hint 1-64: Consider data migration strategy

As noted in the PR objectives, existing data won't automatically include the new field. Consider implementing a data migration strategy to set appropriate default values for existing assets.

Options to consider:

  1. Add a database migration script
  2. Implement fallback logic in the Model() method
  3. Add a background job to update existing records

Would you like assistance in implementing any of these migration strategies?

server/pkg/storytelling/story_bulider_test.go (1)

Line range hint 1-1: Fix typo in filename: "bulider" should be "builder"

The filename contains a typo: story_bulider_test.go should be story_builder_test.go.

server/pkg/storytelling/story_bulider.go (1)

Line range hint 1-1: Fix typo in filename: "bulider" should be "builder"

The filename contains a typo: story_bulider.go should be story_builder.go. This should be corrected for better maintainability and consistency.

server/internal/usecase/interfaces/project.go (1)

26-26: LGTM! Consider adding documentation

The implementation of the optional Core field as *bool is technically sound and maintains backward compatibility.

Consider adding a comment to document the purpose of this field:

+	// Core indicates whether the project supports core functionality
 	Core        *bool
server/internal/infrastructure/mongo/mongodoc/project.go (1)

126-126: Consider grouping related builder calls together.

The Core() builder call could be grouped with other related boolean flags like IsArchived() or IsBasicAuthActive() for better code organization and readability.

server/e2e/gql_project_export_test.go (1)

Line range hint 1-140: Consider improving test maintainability

The test structure is well-organized, but there are a few improvements that could make it more maintainable:

  1. Consider extracting test URLs into constants
  2. Add more descriptive error messages in assertions
  3. Consider adding sub-tests using t.Run() for better test organization

Here's a suggested improvement for the test structure:

 func TestCallExportProject(t *testing.T) {
+    const (
+        testImageURL = "https://test.com/project.jpg"
+        testAssetURL = "http://localhost:8080/assets/01jbbhhtq2jq7mx39dhyq1cfr2.png"
+    )
+
+    t.Run("should successfully export project with external images", func(t *testing.T) {
         e := StartServer(t, &config.Config{
             Origins: []string{"https://example.com"},
             AuthSrv: config.AuthSrvConfig{
                 Disabled: true,
             },
         }, true, baseSeeder)
         // ... rest of the test
+    })
 }
server/pkg/scene/builder/builder.go (2)

95-100: LGTM! Consider adding documentation.

The parameter rename from coreSupport to core improves clarity. Consider adding a documentation comment to explain the purpose of the core parameter.

+// Build writes the scene JSON to the provided writer. The core parameter determines
+// whether core features should be enabled for the scene.
 func (b *Builder) Build(ctx context.Context, w io.Writer, publishedAt time.Time, core bool, enableGa bool, trackingId string) error {

132-137: Improve error handling using fmt.Errorf.

While the parameter rename looks good, the error handling could be improved:

  1. Use fmt.Errorf instead of string concatenation
  2. Make error messages more descriptive
 func (b *Builder) BuildResult(ctx context.Context, publishedAt time.Time, core bool, enableGa bool, trackingId string) (*sceneJSON, error) {
 	if b == nil || b.scene == nil {
 		return nil, errors.New("invalid builder state")
 	}
 	sceneData, err := b.buildScene(ctx, publishedAt, core, enableGa, trackingId)
 	if err != nil {
-		return nil, errors.New("Fail buildScene :" + err.Error())
+		return nil, fmt.Errorf("failed to build scene: %w", err)
 	}
server/e2e/gql_asset_test.go (2)

55-70: Add documentation for the GraphQL mutation.

Consider adding a comment describing the purpose and parameters of this mutation.

+// CreateAssetMutation is a GraphQL mutation for creating assets.
+// Parameters:
+// - teamId: The ID of the team the asset belongs to
+// - file: The file to upload
+// - visualizer: Boolean flag indicating if the asset should be visible in the visualizer
 const CreateAssetMutation = `mutation CreateAsset($teamId: ID!, $file: Upload!, $visualizer: Boolean!) {

103-141: Add documentation for the GraphQL query.

Consider adding a comment describing the purpose and parameters of this query.

+// GetAssetsQuery is a GraphQL query for retrieving assets with pagination and sorting.
+// Parameters:
+// - teamId: The ID of the team to fetch assets from
+// - pagination: Optional pagination parameters
+// - keyword: Optional search keyword
+// - sort: Optional sorting parameters
 const GetAssetsQuery = `query GetAssets($teamId: ID!, $pagination: Pagination, $keyword: String, $sort: AssetSort) {
server/pkg/storytelling/story.go (1)

105-106: Consider adding a setter method for the core field.

While the getter method is properly implemented, there's no corresponding setter method. This might limit the ability to modify the core status after creation.

Consider adding a setter method:

+func (s *Story) SetCore(core bool) {
+    s.core = core
+    s.updatedAt = util.Now()
+}
server/pkg/scene/builder/scene.go (2)

26-28: Add documentation for the new configuration fields.

The new fields lack documentation explaining their purpose and usage. Consider adding comments to clarify:

  • What the Core flag represents and its impact
  • When EnableGA should be true/false
  • Expected format and purpose of TrackingID
 type sceneJSON struct {
+    // Core indicates whether the scene supports core functionality
     Core              bool                    `json:"core"`
+    // EnableGA determines if Google Analytics tracking is enabled
     EnableGA          bool                    `json:"enableGa"`
+    // TrackingID specifies the Google Analytics tracking identifier
     TrackingID        string                  `json:"trackingId"`
 }

31-31: Consider adding parameter validation and documentation.

The method could benefit from:

  1. Documentation explaining the parameters and their requirements
  2. Input validation for trackingId when enableGa is true
+// sceneJSON creates a JSON representation of the scene with the specified configuration.
+// Parameters:
+//   - ctx: Context for the operation
+//   - publishedAt: Time when the scene was published
+//   - l: List of layer JSON objects
+//   - p: List of properties
+//   - core: Whether core functionality is enabled
+//   - enableGa: Whether Google Analytics is enabled
+//   - trackingId: Google Analytics tracking ID (required if enableGa is true)
 func (b *Builder) sceneJSON(ctx context.Context, publishedAt time.Time, l []*layerJSON, p []*property.Property, core bool, enableGa bool, trackingId string) (*sceneJSON, error) {
+    if enableGa && trackingId == "" {
+        return nil, fmt.Errorf("tracking ID is required when Google Analytics is enabled")
+    }
     tags, err := b.tags(ctx)
     if err != nil {
         return nil, err
     }
     // ... rest of the implementation
 }

Also applies to: 48-50

server/internal/usecase/interactor/project_test.go (2)

75-75: Add documentation for the Core field

The test cases properly cover both true and false values for the new Core field. However, it would be helpful to add documentation explaining what this field represents and its significance in the project context.

Consider adding a comment above the test cases explaining the purpose and impact of the Core field.

Also applies to: 90-90, 106-106


GraphQL schema needs to be updated for the Core field

The Core field is missing from the Project type in the GraphQL schema, although it's present in the CreateProjectInput. This needs to be addressed:

  • server/gql/project.graphql: Add the Core field to the Project type definition
  • The field is properly defined in CreateProjectInput but missing in UpdateProjectInput
  • No database migration appears to be present for this new field
🔗 Analysis chain

Line range hint 75-106: Verify related changes for the Core field

Since this introduces a new Core field to projects, we should verify related changes:


Let me check the GraphQL schema and migrations to verify if the Core field is properly defined.


Let me check for any Core field definitions in the GraphQL schema input types and mutations, as well as look for any recent migration files that might contain Core field additions.


Let me check the content of the GraphQL input types to verify if the Core field is properly defined in the schema.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for related Core field changes in UI, GraphQL schema, and migrations

# Check for UI components using the Core field
rg -g '*.{tsx,jsx}' -A 3 'core.*project'

# Check for GraphQL schema changes
rg -g '*.graphql' 'type Project'

# Check for database migrations
fd -g '*migration*.{go,sql}'

Length of output: 465


Script:

#!/bin/bash
# Check GraphQL schema for Core field
rg -g '*.graphql' -A 10 'type Project'

# Check recent migrations for Core field
cat server/internal/infrastructure/mongo/migration/migrations.go

Length of output: 3062


Script:

#!/bin/bash
# Check GraphQL schema for Core field in input types and mutations
rg -g '*.graphql' 'input.*Project|mutation.*project'

# Check for recent migration files
fd -e go -e sql . server/internal/infrastructure/mongo/migration/

Length of output: 1860


Script:

#!/bin/bash
# Check GraphQL input types for Core field
rg -g '*.graphql' -A 10 'input CreateProjectInput|input UpdateProjectInput'

# Also check the Project type definition again to ensure we didn't miss the Core field
rg -g '*.graphql' -A 15 'type Project implements Node'

Length of output: 1954

server/pkg/project/project_test.go (1)

Line range hint 324-346: Test function name doesn't match tested functionality

The test function name TestProject_Experimental should be renamed to TestProject_Core to accurately reflect the functionality being tested. This improves code maintainability and makes it easier for developers to understand the purpose of the test.

-func TestProject_Experimental(t *testing.T) {
+func TestProject_Core(t *testing.T) {
     tests := []struct {
         name     string
         p        *Project
         expected bool
     }{
server/internal/usecase/interactor/scene_test.go (2)

Line range hint 1-194: Test structure needs improvement

The test could be improved in several ways:

  1. The test data is a large inline JSON string which makes it hard to maintain
  2. The test only covers the "happy path" with core: true
  3. Missing test cases for core: false and when the field is absent

Consider refactoring the test to:

  1. Move the test data to a separate test fixture file
  2. Add test cases for different core values using table-driven tests
  3. Add assertions specifically for the core field behavior

Here's a suggested refactor for the test structure:

 func TestImportScene(t *testing.T) {
+    tests := []struct {
+        name     string
+        coreVal  *bool
+        wantErr  bool
+    }{
+        {
+            name:    "with core true",
+            coreVal: lo.ToPtr(true),
+            wantErr: false,
+        },
+        {
+            name:    "with core false",
+            coreVal: lo.ToPtr(false),
+            wantErr: false,
+        },
+        {
+            name:    "without core field",
+            coreVal: nil,
+            wantErr: false,
+        },
+    }
+
+    for _, tt := range tests {
+        t.Run(tt.name, func(t *testing.T) {
+            // ... test setup ...
+            
+            // Modify test data based on test case
+            if tt.coreVal != nil {
+                sceneData["core"] = *tt.coreVal
+            }
+            
+            // ... rest of the test ...
+        })
+    }
 }

Line range hint 151-194: Improve test assertions

The test removes several fields before comparison but doesn't document why these fields are excluded. This makes it harder to understand the test's intentions and maintain it.

Consider:

  1. Adding comments explaining why each field is excluded
  2. Creating helper functions for field exclusion
  3. Adding specific assertions for important fields before the JSON comparison

Example:

+    // Helper to exclude dynamic fields that change on each test run
+    func excludeDynamicFields(m map[string]interface{}) {
+        // IDs are generated dynamically
+        delete(m, "rootLayerId")
+        delete(m, "propertyId")
+        // Timestamps change on each run
+        delete(m, "updatedAt")
+        delete(m, "createdAt")
+    }

     // actual
     temp := gqlmodel.ToScene(result)
     resultJSON, err := json.Marshal(temp)
     assert.NoError(t, err)

     var resultMap map[string]interface{}
     err = json.Unmarshal(resultJSON, &resultMap)
     assert.NoError(t, err)
-    delete(resultMap, "rootLayerId")
-    delete(resultMap, "propertyId")
-    delete(resultMap, "updatedAt")
-    delete(resultMap, "createdAt")
+    excludeDynamicFields(resultMap)

+    // Assert important fields before JSON comparison
+    assert.Equal(t, sceneData["core"], resultMap["core"], "core field should match input")
server/pkg/project/builder_test.go (2)

57-58: Consider adding more test scenarios for Core functionality

While the basic test case looks good, consider adding more scenarios to thoroughly test the Core functionality:

  1. Default value when not set
  2. Setting to false explicitly
  3. Multiple toggles of the value

Example test cases to add:

func TestBuilder_Experimental(t *testing.T) {
	var tb = New().NewID()
-	res := tb.Core(true).MustBuild()
-	assert.True(t, res.Core())
+	t.Run("default value", func(t *testing.T) {
+		res := tb.MustBuild()
+		assert.False(t, res.Core())
+	})
+	
+	t.Run("set to true", func(t *testing.T) {
+		res := tb.Core(true).MustBuild()
+		assert.True(t, res.Core())
+	})
+	
+	t.Run("set to false", func(t *testing.T) {
+		res := tb.Core(false).MustBuild()
+		assert.False(t, res.Core())
+	})
+	
+	t.Run("toggle multiple times", func(t *testing.T) {
+		res := tb.Core(true).Core(false).Core(true).MustBuild()
+		assert.True(t, res.Core())
+	})
}

Line range hint 266-267: Update Build and MustBuild tests to include Core field

The comprehensive test cases in TestBuilder_Build and TestBuilder_MustBuild should be updated to include the Core field in their test scenarios.

Add the Core field to the test structs and assertions:

 type args struct {
     name, description  string
     alias, publicTitle string
     publicDescription  string
     publicImage        string
     id                 ID
     isArchived         bool
+    core              bool
     updatedAt          time.Time
     // ... other fields ...
 }

Update the test cases to include Core scenarios:

 {
     name: "build normal project",
     args: args{
         name:              "xxx.aaa",
         description:       "ddd",
+        core:             true,
         // ... other fields ...
     },
     expected: &Project{
         id:                pid,
         description:       "ddd",
+        core:             true,
         // ... other fields ...
     },
 }

Also update the builder chain in both test functions:

 return New().
     ID(tt.args.id).
+    Core(tt.args.core).
     // ... other builder calls ...
     MustBuild()

Also applies to: 379-380

server/e2e/gql_project_test.go (1)

164-164: Consider extracting ProjectFragment to reduce duplication

The ProjectFragment is duplicated in two locations (lines 164 and 427) with identical fields. Consider extracting it into a shared GraphQL fragment file or constant to maintain DRY principles and ensure consistency.

Example approach:

const projectFragment = `
fragment ProjectFragment on Project {
    id
    name
    description
    imageUrl
    isArchived
    isBasicAuthActive
    basicAuthUsername
    basicAuthPassword
    publicTitle
    publicDescription
    publicImage
    alias
    enableGa
    trackingId
    publishmentStatus
    updatedAt
    createdAt
    core
    starred
    __typename
}`

// Then in your tests:
query := fmt.Sprintf(`
    query GetProjects($teamId: ID!, $pagination: Pagination, $keyword: String, $sort: ProjectSort) {
        projects(/*...*/) {
            /*...*/
        }
    }
    %s`, projectFragment)

Also applies to: 427-427

server/internal/usecase/interactor/project.go (2)

155-156: Add validation for the Core field

Consider adding validation for the Core field to ensure it meets any business requirements or constraints.


324-324: Document the purpose and impact of the Core field

The Core field is used during scene building, but its purpose and impact on the scene building process are not documented. Consider adding documentation to explain:

  • What the Core field represents
  • How it affects scene building
  • Any constraints or requirements

Also applies to: 440-440

server/e2e/gql_nlslayer_test.go (3)

Line range hint 825-854: Consider adding schema validation and error case handling

The addCustomProperties helper function could be more robust:

  1. Add schema structure validation before sending the request
  2. Add test cases for error scenarios (invalid schema, invalid layer ID)
 func addCustomProperties(
 	e *httpexpect.Expect,
 	layerId string,
 	schema map[string]any,
 ) (GraphQLRequest, *httpexpect.Value) {
+	// Validate required schema fields
+	if schema == nil {
+		panic("schema cannot be nil")
+	}
+	requiredFields := []string{"id", "type"}
+	for _, field := range requiredFields {
+		if _, ok := schema[field]; !ok {
+			panic(fmt.Sprintf("schema missing required field: %s", field))
+		}
+	}
+
 	requestBody := GraphQLRequest{
 		OperationName: "AddCustomProperties",
 		Query: `mutation AddCustomProperties($input: AddCustomPropertySchemaInput!) {

Line range hint 856-935: Enhance test coverage with edge cases

The TestCustomProperties function would benefit from additional test cases:

  1. Negative test cases (invalid schema)
  2. Boundary testing for extrudedHeight
  3. Validation of positions array length
  4. Error scenarios (non-existent layer)
 func TestCustomProperties(t *testing.T) {
+	t.Run("invalid schema", func(t *testing.T) {
+		// Test with missing required fields
+		invalidSchema := map[string]any{
+			"extrudedHeight": 0,
+		}
+		// Expect error response
+	})
+
+	t.Run("boundary values", func(t *testing.T) {
+		// Test extreme values for extrudedHeight
+		// Test empty and large positions arrays
+	})
+
+	t.Run("non-existent layer", func(t *testing.T) {
+		// Test with invalid layer ID
+		// Expect appropriate error response
+	})

Line range hint 485-515: Remove or document commented-out code

The removeNLSInfobox function is commented out without any explanation. Either:

  1. Remove it if it's no longer needed
  2. Document why it's kept for future reference
server/internal/usecase/interactor/scene.go (1)

128-130: Consider extracting visualizer selection logic.

The visualizer selection logic is repeated in multiple places. Consider extracting this into a helper method to improve maintainability and reduce duplication.

+func getVisualizer(isCore bool) visualizer.Visualizer {
+    if isCore {
+        return visualizer.VisualizerCesiumBeta
+    }
+    return visualizer.VisualizerCesium
+}

Then use it in the code:

-var viz = visualizer.VisualizerCesium
-if prj.Core() {
-    viz = visualizer.VisualizerCesiumBeta
-}
+viz := getVisualizer(prj.Core())

Also applies to: 632-632, 809-811

server/e2e/gql_storytelling_test.go (1)

1051-1051: Test assertion needs to be more specific

The test assertion includes "core":true in the regex pattern, but it's mixed with many other fields. Consider extracting core-specific assertions for better test clarity.

-	pub := regexp.MustCompile(fmt.Sprintf(`{"schemaVersion":1,"id":"%s","publishedAt":".*","property":{"tiles":\[{"id":".*"}]},"plugins":{},"layers":null,"widgets":\[],"widgetAlignSystem":null,"tags":\[],"clusters":\[],"story":{"id":"%s","title":"","property":{},"pages":\[{"id":"%s","property":{},"title":"test","blocks":\[{"id":"%s","property":{"default":{"text":"test value"},"panel":{"padding":{"top":2,"bottom":3,"left":0,"right":1}}},"plugins":null,"extensionId":"%s","pluginId":"%s"}],"swipeable":true,"swipeableLayers":\[],"layers":\[]}],"position":"left","bgColor":""},"nlsLayers":null,"layerStyles":null,"core":true,"enableGa":false,"trackingId":""}`, sID, storyID, pageID, blockID, extensionId, pluginId))
+	expectedCore := `"core":true`
+	expectedFormat := fmt.Sprintf(`{"schemaVersion":1,"id":"%s","publishedAt":".*","property":{"tiles":\[{"id":".*"}]},"plugins":{},"layers":null,"widgets":\[],"widgetAlignSystem":null,"tags":\[],"clusters":\[],"story":{"id":"%s","title":"","property":{},"pages":\[{"id":"%s","property":{},"title":"test","blocks":\[{"id":"%s","property":{"default":{"text":"test value"},"panel":{"padding":{"top":2,"bottom":3,"left":0,"right":1}}},"plugins":null,"extensionId":"%s","pluginId":"%s"}],"swipeable":true,"swipeableLayers":\[],"layers":\[]}],"position":"left","bgColor":""},"nlsLayers":null,"layerStyles":null,%s,"enableGa":false,"trackingId":""}`, sID, storyID, pageID, blockID, extensionId, pluginId, expectedCore)
+	pub := regexp.MustCompile(expectedFormat)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 948e16f and 6f0ea74.

⛔ Files ignored due to path filters (2)
  • server/e2e/test.csv is excluded by !**/*.csv
  • server/e2e/test.png is excluded by !**/*.png
📒 Files selected for processing (40)
  • server/e2e/gql_asset_test.go (1 hunks)
  • server/e2e/gql_nlslayer_test.go (1 hunks)
  • server/e2e/gql_project_export_test.go (2 hunks)
  • server/e2e/gql_project_test.go (5 hunks)
  • server/e2e/gql_storytelling_test.go (3 hunks)
  • server/gql/asset.graphql (3 hunks)
  • server/gql/project.graphql (2 hunks)
  • server/internal/adapter/gql/generated.go (26 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_asset.go (1 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_project.go (1 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_project_test.go (2 hunks)
  • server/internal/adapter/gql/gqlmodel/models_gen.go (4 hunks)
  • server/internal/adapter/gql/resolver_mutation_asset.go (1 hunks)
  • server/internal/adapter/gql/resolver_mutation_project.go (1 hunks)
  • server/internal/adapter/gql/resolver_mutation_property.go (1 hunks)
  • server/internal/infrastructure/memory/asset.go (1 hunks)
  • server/internal/infrastructure/mongo/asset.go (2 hunks)
  • server/internal/infrastructure/mongo/mongodoc/asset.go (3 hunks)
  • server/internal/infrastructure/mongo/mongodoc/project.go (3 hunks)
  • server/internal/usecase/interactor/asset.go (1 hunks)
  • server/internal/usecase/interactor/asset_test.go (2 hunks)
  • server/internal/usecase/interactor/project.go (4 hunks)
  • server/internal/usecase/interactor/project_test.go (5 hunks)
  • server/internal/usecase/interactor/scene.go (3 hunks)
  • server/internal/usecase/interactor/scene_test.go (1 hunks)
  • server/internal/usecase/interfaces/asset.go (1 hunks)
  • server/internal/usecase/interfaces/project.go (1 hunks)
  • server/internal/usecase/interfaces/published.go (3 hunks)
  • server/pkg/asset/asset.go (2 hunks)
  • server/pkg/asset/asset_test.go (4 hunks)
  • server/pkg/asset/builder.go (1 hunks)
  • server/pkg/project/builder.go (1 hunks)
  • server/pkg/project/builder_test.go (1 hunks)
  • server/pkg/project/project.go (2 hunks)
  • server/pkg/project/project_test.go (2 hunks)
  • server/pkg/scene/builder/builder.go (4 hunks)
  • server/pkg/scene/builder/scene.go (2 hunks)
  • server/pkg/storytelling/story.go (2 hunks)
  • server/pkg/storytelling/story_bulider.go (1 hunks)
  • server/pkg/storytelling/story_bulider_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • server/gql/asset.graphql
  • server/internal/adapter/gql/gqlmodel/convert_asset.go
  • server/internal/adapter/gql/gqlmodel/models_gen.go
  • server/internal/adapter/gql/resolver_mutation_asset.go
  • server/internal/adapter/gql/resolver_mutation_property.go
  • server/internal/infrastructure/memory/asset.go
  • server/internal/infrastructure/mongo/asset.go
  • server/internal/usecase/interactor/asset.go
  • server/internal/usecase/interactor/asset_test.go
  • server/internal/usecase/interfaces/asset.go
  • server/pkg/asset/asset.go
  • server/pkg/asset/asset_test.go
  • server/pkg/asset/builder.go
🔇 Additional comments (31)
server/internal/adapter/gql/generated.go (4)

14680-14709: LGTM! Resolver implementations follow best practices

The resolver implementations for both Asset and Project types are well-structured with:

  • Proper error handling and null checks
  • Thread-safe panic recovery
  • Correct context propagation

Also applies to: 39826-39840


64336-64340: LGTM! Concurrent field resolution is properly implemented

The core field is correctly integrated into the concurrent field resolution system with:

  • Thread-safe invalid field counting
  • Proper null handling
  • Consistent implementation pattern

Also applies to: 71480-71484


14829-14830: LGTM! Field context handlers are properly implemented

The field context handlers for the core field are correctly implemented with:

  • Proper field registration
  • Consistent error handling
  • Clear error messages

Also applies to: 39857-39866, 40265-40266


Line range hint 59847-59867: Verify consistent handling of the core field

The implementation correctly handles the core field as:

  • Required for new assets
  • Optional for project updates

Let's verify this is consistently handled across the codebase.

Also applies to: 59942-60004

✅ Verification successful

Based on the shell script results, I can now generate the final response:

Core field handling is consistently implemented across the codebase

The verification confirms that:

  • CreateAssetInput consistently requires the core field as a non-optional boolean in both GraphQL schema and Go implementation
  • UpdateProjectInput correctly makes all fields optional, including core-related fields
  • The implementation in resolvers and interactors maintains this contract
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent handling of core field in mutations and queries

# Check for any GraphQL operations that might be missing the core field
rg -A 5 'mutation.*CreateAsset|query.*assets' --type graphql

# Check for any direct database operations that might need updating
rg -A 5 'CreateAsset|UpdateProject' --type go

Length of output: 31856

server/internal/usecase/interfaces/published.go (3)

28-28: LGTM! The struct field follows Go conventions.

The Core field is properly defined with the appropriate JSON tag and omitempty option for backward compatibility.


Line range hint 17-40: Clarify the relationship between visualizer and core flags.

The PR objectives mention adding a visualizer flag to assets, but these changes introduce a core flag in project metadata. Could you please clarify:

  1. Is there a relationship between the visualizer and core flags?
  2. Are these changes part of the same feature or a separate concern?
✅ Verification successful

Let me search for more context about the relationship between these flags.


Based on the search results, I can now generate a final response as there's clear evidence about the relationship between the core flag and visualizer functionality.

The core flag is part of the visualizer feature set

The changes are consistent with the PR objectives. The core flag (coreSupport) is directly related to the visualizer functionality as evidenced by:

  1. It's used alongside the visualizer parameter in project creation (see CreateProjectDocument mutation)
  2. The changelog shows it was added as part of visualizer features:
  3. It's connected to experimental/advanced visualizer features in the builtin manifests (experimental_core)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for visualizer-related code to understand the relationship
# Expected: Find connections between visualizer and core flags

# Search for visualizer-related code
rg -i "visualizer.*flag|flag.*visualizer"

# Search for core flag usage
rg -i "core.*flag|flag.*core"

Length of output: 1628


Script:

#!/bin/bash
# Search for PR #424 and #448 to understand the relationship between core and visualizer flags
gh pr view 424 || true
gh pr view 448 || true

# Search for any mentions of core support or experimental core in the codebase
rg -i "coresupport|experimental.*core|core.*experimental" -A 3 -B 3

Length of output: 95501


17-17: Verify interface implementations and add documentation.

The renamed method Core() needs to be implemented by all types that implement HasPublicMeta. Additionally, consider adding documentation to explain the purpose of this flag.

✅ Verification successful

Core() method is properly implemented and used across the codebase

The verification shows that the Core() method is implemented by multiple types (Project, Story, and Asset) and is actively used throughout the codebase in various contexts including:

  • MongoDB document conversion
  • GraphQL model conversion
  • Scene and project operations
  • Asset filtering

The rename from CoreSupport() to Core() is consistent with the implementations and usages.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all implementations of HasPublicMeta interface to ensure they're updated
# Expected: All implementations should have the Core() method

# Search for struct types that might implement the interface
ast-grep --pattern 'type $_ struct {
  $$$
}'

# Search for Core() method implementations
ast-grep --pattern 'func ($_ $_) Core() bool {
  $$$
}'

Length of output: 102156


Script:

#!/bin/bash
# Let's try a different approach to find Core() implementations
# Search for Core() method implementations in the codebase
rg -g '*.go' 'func \([^)]+\) Core\(\) bool'

# Also search for any references to Core() method
rg -g '*.go' '\.Core\(\)'

Length of output: 1292

server/internal/infrastructure/mongo/mongodoc/asset.go (2)

63-63: LGTM!

The Core field mapping is correctly implemented using the builder pattern, maintaining consistency with the existing codebase structure.


41-41: Verify the Core() method implementation

The code assumes the existence of a Core() method in the asset package.

Let's verify the method implementation:

✅ Verification successful

Core() method is properly implemented in the asset package

The verification confirms that the Core() method is correctly implemented in server/pkg/asset/asset.go and returns a boolean value, making the usage in the mongodoc package valid.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if Core() method exists in the asset package
ast-grep --pattern 'func \($_\) Core() bool {
  $$$
}'

Length of output: 56


Script:

#!/bin/bash
# Let's try a broader search for Core() method without assuming the return type
ast-grep --pattern 'func \($_\) Core() $_'

# Also search for Core() method using ripgrep for better coverage
rg "func.*Core\(\)" -A 2

Length of output: 487

server/pkg/storytelling/story_bulider.go (1)

25-25: Verify the unconditional core flag assignment

The core field is always set to true without any conditional logic. Consider if this is the intended behavior or if it should be configurable through the builder pattern like other fields.

✅ Verification successful

Let me analyze the results and generate additional verification scripts to understand the usage pattern of the core field across the codebase.


Let me try one more verification to understand the Story builder pattern usage:


Based on the comprehensive analysis of the codebase, I can now provide the final response:

Hardcoded core flag is the intended behavior

The core field being set to true unconditionally in the Story builder is correct because:

  1. The Story builder is used in controlled contexts where core stories are created, as seen in internal/usecase/interactor/storytelling.go
  2. The field is properly exposed through a getter method Core() and is used in the GraphQL layer
  3. Other entities (Project, Asset) also use this field with configurable values through their builders, showing a consistent pattern across the codebase
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any conditional usage of the core field
rg -A 5 "core\s*[:=]" --type go

Length of output: 5633


Script:

#!/bin/bash
# Search for the Story struct definition and its core field
ast-grep --pattern 'type Story struct {
  $$$
  core $$$
  $$$
}'

# Search for any Story creation or core field usage in tests
rg -B 3 -A 3 "NewStory|Story{|StoryBuilder" --type go

Length of output: 1545


Script:

#!/bin/bash
# Search for Story builder usage and core field initialization
rg -B 3 -A 3 "NewStory|Story\{|StoryBuilder" --type go

# Search for any methods that check or use the core field in Story
ast-grep --pattern 'func ($_) Core() bool {
  $$$
}'

Length of output: 21694

server/gql/project.graphql (1)

23-23: Verify the impact of making core a required field

The core field is marked as non-nullable (Boolean!), which means existing projects in the database must have this field populated.

Let's verify the database migration strategy:

✅ Verification successful

Core field is already part of the Project model with default value handling

The verification shows that:

  • The core field already exists in the Project model (server/pkg/project/project.go)
  • It has a getter method Core() implemented
  • The field is a boolean type at the model level
  • No explicit migrations were found, suggesting MongoDB is used which is schema-less

Since MongoDB is being used (which is schema-less) and the field already exists in the model with proper getter methods, making it non-nullable in GraphQL schema is safe as:

  1. Existing documents will return false for undefined boolean fields in MongoDB
  2. The model already handles the field, so new projects will have it defined
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there's a migration file for this change
fd -e go -e sql migration | rg -i "core|project"

# Check if there are any database-related tests
fd -e go test | rg -i "test.*project.*core"

Length of output: 96


Script:

#!/bin/bash
# Let's check for database schema changes or migrations in a broader scope
fd migration

# Look for any SQL files that might contain schema changes
fd -e sql

# Check for database related code
rg -i "database.*project.*core" -g "!{test,vendor}/**"

# Look for project-related model definitions
rg -i "type\s+Project\s+struct" -A 10

# Check for any database initialization or schema setup
rg -i "createtable.*project" -g "*.{sql,go}"

Length of output: 4910


Script:

#!/bin/bash
# Let's check the mongo migrations since we found mongo infrastructure
rg -i "core" server/internal/infrastructure/mongo/migration/ -A 5

# Check the project model and repository for core field
rg -i "core" server/pkg/project/project.go -A 5

# Look for core field in mongo schema
rg -i "core" server/internal/infrastructure/mongo/project.go -A 5

# Check for any default value handling in project creation
rg -i "NewProject.*core" -g "*.go"

Length of output: 475

server/internal/adapter/gql/gqlmodel/convert_project_test.go (1)

72-72: Verify the field renaming across the codebase

Let's ensure this renaming is consistently applied across related files.

Also applies to: 96-96

✅ Verification successful

Field renaming from CoreSupport to Core is consistently applied

The verification shows that:

  • No remaining instances of "CoreSupport" were found in the codebase
  • "Core" field is consistently used as a boolean type across:
    • Generated models in models_gen.go
    • Project builder in builder.go
    • Project entity in project.go
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining instances of CoreSupport and verify Core field usage

# Check for any remaining instances of CoreSupport
echo "Checking for remaining CoreSupport instances:"
rg "CoreSupport" --type go

# Check Core field usage in related files
echo "Checking Core field usage in related files:"
rg "Core.*bool" --type go server/internal/adapter/gql/gqlmodel/
rg "Core.*bool" --type go server/pkg/project/

Length of output: 852

server/pkg/project/builder.go (2)

125-126: Implementation follows established patterns

The Core method implementation is clean and consistent with other builder methods in the file, properly following the builder pattern with method chaining.


125-126: Verify if this change is within the PR scope

This change introduces a Core method to set a core flag on projects, but the PR objectives specifically mention adding a visualizer flag to assets. Could you clarify if this change is necessary for the visualizer feature or if it should be in a separate PR?

Let's check for any connections between the core and visualizer features:

✅ Verification successful

The Core method change is correctly scoped and necessary

The change is part of the project's core functionality and is correctly scoped. From the evidence:

  1. The core field is a fundamental part of the Project model, as shown in project.go
  2. The GraphQL schema shows core is an optional boolean field in CreateProjectInput
  3. The field is used in project creation through the GraphQL mutation resolver

The change from CoreSupport to Core aligns with the field name in both the GraphQL schema and the Project model, making the codebase more consistent.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for relationships between core and visualizer in the codebase
rg -l "core.*visualizer|visualizer.*core" --type go

# Check if the core field is used in asset-related code
rg "core.*asset|asset.*core" --type go

Length of output: 240


Script:

#!/bin/bash
# Let's check the content of these files to understand the relationship
echo "=== server/e2e/gql_storytelling_test.go ==="
rg -A 5 -B 5 "core.*visualizer|visualizer.*core" server/e2e/gql_storytelling_test.go

echo -e "\n=== server/e2e/gql_project_test.go ==="
rg -A 5 -B 5 "core.*visualizer|visualizer.*core" server/e2e/gql_project_test.go

echo -e "\n=== server/e2e/gql_project_export_test.go ==="
rg -A 5 -B 5 "core.*visualizer|visualizer.*core" server/e2e/gql_project_export_test.go

# Let's also check the PR changes to understand the context better
echo -e "\n=== Changes to core and visualizer related files ==="
fd -e go -e graphql -e gql | xargs rg "core|visualizer" -l

# Check if there are any GraphQL schema changes related to this
echo -e "\n=== GraphQL schema changes ==="
fd "schema.graphql$" | xargs cat

Length of output: 4943


Script:

#!/bin/bash
# Let's check the project.graphql file for the schema definition
echo "=== Project GraphQL Schema ==="
cat server/gql/project.graphql

# Let's also check the project model and its relationship with visualizer
echo -e "\n=== Project Model ==="
cat server/pkg/project/project.go

# Check the actual implementation of project creation
echo -e "\n=== Project Creation Implementation ==="
cat server/internal/adapter/gql/resolver_mutation_project.go

Length of output: 19644

server/internal/infrastructure/mongo/mongodoc/project.go (1)

33-33: Please clarify the purpose of the Core field and document its impact.

The addition of the Core field (renamed from CoreSupport) needs clarification:

  1. What is the purpose of this field and how does it relate to the visualizer flag mentioned in the PR objectives?
  2. How will existing data be migrated from CoreSupport to Core?
  3. Consider adding documentation to explain the field's purpose.

Let's check for any existing documentation or references:

✅ Verification successful

The Core field is a documented feature and its renaming is justified

Based on the changelog entries and codebase analysis:

  1. The field was initially added as coreSupport in PR feat(server): add coreSupport flag to project #424
  2. It's related to the experimental core features mentioned in PR refactor(web): Beta tab routing #448
  3. The field exists consistently across the project model in multiple layers (pkg/project/project.go, gqlmodel, mongodoc)
  4. The renaming from CoreSupport to Core aligns with the codebase's evolution towards core feature support

The change is well-documented in the project's history and appears to be part of a broader feature implementation rather than an isolated change.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any documentation or usage of Core/CoreSupport
rg -i "coresupport|core.*support|core.*flag" --type md

Length of output: 598


Script:

#!/bin/bash
# Let's check the PR history and related files for more context
rg -l "CoreSupport|coreSupport" --type go

# Also check for any Core-related fields in the project model
ast-grep --pattern 'type Project struct {
  $$$
}'

Length of output: 7151


Script:

#!/bin/bash
# Let's check the changelog entries and related commits for context about the Core field
rg -A 5 "core.*flag|coresupport" CHANGELOG.md

# Also check if there are any migrations related to this field
fd migration --type f --exec rg -l "CoreSupport|core.*support|core.*flag" {}

Length of output: 2755

server/pkg/scene/builder/builder.go (1)

169-169: Verify the impact on scene JSON generation.

The parameter rename is consistent, but we should verify that the core parameter is correctly handled in the sceneJSON method and the final JSON output.

Also applies to: 186-186

✅ Verification successful

Parameter rename is correctly handled in scene JSON generation

The verification shows that:

  • The core parameter is correctly passed through from buildScene to sceneJSON method
  • The sceneJSON struct has a corresponding Core field with proper JSON serialization tag json:"core"
  • The parameter is properly assigned in the struct initialization at line 48: Core: core
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how the core parameter affects scene JSON generation

# Search for sceneJSON method implementation
ast-grep --pattern 'func (b *Builder) sceneJSON($$$) (*sceneJSON, error) {
  $$$
}'

# Search for sceneJSON struct definition
ast-grep --pattern 'type sceneJSON struct {
  $$$
}'

Length of output: 3430

server/e2e/gql_asset_test.go (1)

12-53: Improve test structure and resource management.

The test function needs improvements in several areas:

  1. Test data management
  2. Resource cleanup
  3. Test case organization
  4. Error cases coverage

The previous review comment suggesting comprehensive test coverage improvements is still valid. Please refer to that comment for the detailed implementation suggestion.

server/pkg/storytelling/story.go (1)

29-29: Verify the purpose of the core field.

There appears to be a discrepancy between:

  • PR objectives: Mentions adding a "visualizer flag"
  • Actual changes: Adds a "core" field
  • AI summary: Describes this as a rename from coreSupport

Please clarify if this is:

  1. A new field for a different feature
  2. The visualizer flag with a different name
  3. A rename as suggested by the AI summary
server/pkg/project/project.go (3)

36-36: LGTM! Field addition follows Go conventions.

The core field is appropriately placed and follows Go conventions for field naming and visibility.


109-110: LGTM! Getter method is consistent with codebase patterns.

The Core() method follows the established getter pattern used throughout the codebase and maintains proper encapsulation.


36-36: Please clarify the relationship between Project.core and asset visualizer flag.

The PR description mentions adding a visualizer flag to assets, but these changes introduce a core field to the Project struct. Could you please clarify:

  1. How does the Project.core field relate to the asset visualizer feature?
  2. Are there any dependencies or interactions between projects and assets that should be documented?

Let's check for any relationships between projects and assets:

Also applies to: 109-110

✅ Verification successful

Let me gather more information about the asset and project structures to understand their relationship better.


The core field is a consistent pattern across both Project and Asset entities

Looking at the codebase, I can see that both Project and Asset structs have a core boolean field, and both provide a Core() method. This appears to be a deliberate architectural pattern rather than an inconsistency. The PR's changes align with this pattern by:

  1. Both entities (Asset and Project) have identical core field implementations
  2. The field is used in scene building context (as seen in scene/builder)
  3. Both structs expose the field through a Core() method with identical signatures
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any connections between projects and assets
rg -l 'asset.*project|project.*asset' --type go

# Search for any usage of the new core field
ast-grep --pattern 'core'

Length of output: 1922


Script:

#!/bin/bash
# Check the Project struct definition
ast-grep --pattern 'type Project struct {
  $$$
}'

# Check the Asset struct definition
ast-grep --pattern 'type Asset struct {
  $$$
}'

# Look for Core() method implementations
ast-grep --pattern 'func ($_ $_) Core() bool {
  $$$
}'

Length of output: 10022

server/pkg/scene/builder/scene.go (1)

26-26: Verify the integration between scenes and assets.

The addition of the Core flag to scenes appears to be related to the asset management system changes mentioned in the PR objectives. Let's verify this integration:

Also applies to: 31-31

✅ Verification successful

Let me gather more information about the Core field usage and its potential impact.


Based on the results, I can now provide a final response:

The Core flag addition is a safe and well-integrated change

The Core boolean field is consistently implemented across multiple layers of the application:

  • Scene builder (server/pkg/scene/builder/scene.go)
  • GraphQL models (internal/adapter/gql/gqlmodel/models_gen.go)
  • MongoDB documents (internal/infrastructure/mongo/mongodoc/project.go)
  • Asset-related interfaces (internal/usecase/interfaces/asset.go)

The field is properly serialized with JSON tags and follows the same pattern as other boolean flags in the scene structure (like EnableGA). There are no circular dependencies between scene and asset packages, and the integration appears to be clean.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how scenes and assets are integrated with respect to the Core flag

# Check for references to scene.Core in asset-related code
echo "Checking asset-scene integration..."
rg -l "scene.*Core" --type go

# Check for any potential circular dependencies
echo "Checking for circular dependencies..."
ast-grep --pattern 'import \( 
  $$$
  "github.com/reearth/reearth/server/pkg/asset"
  $$$
\)' server/pkg/scene

ast-grep --pattern 'import \(
  $$$
  "github.com/reearth/reearth/server/pkg/scene"
  $$$
\)' server/pkg/asset

Length of output: 424


Script:

#!/bin/bash
# Check for any usage of the Core field in scene-related code
echo "Checking Core field usage in scene package..."
rg -A 3 "Core\s+bool" --type go

# Check for any references to Core in tests or implementations
echo "Checking Core references in tests and implementations..."
rg -A 3 "\.Core\s*=" --type go

# Check for any scene builder usage patterns
echo "Checking scene builder usage..."
rg -l "scene/builder" --type go

# Look for any validation or business logic related to Core
echo "Checking for Core-related logic..."
ast-grep --pattern 'func $_($$$ *Scene $$$) {
  $$$
  Core
  $$$
}'

Length of output: 4620

server/internal/usecase/interactor/scene_test.go (1)

143-143: Verify alignment with PR objectives

The PR objectives mention adding a visualizer flag to assets, but this test adds a core field to scenes. This seems to be a different feature than what was described in the PR objectives.

Let's verify if there are any asset-related changes that should accompany this scene change:

server/internal/adapter/gql/resolver_mutation_project.go (2)

Line range hint 1-424: Ensure comprehensive testing for the Core field

Given the complexity of project operations, particularly in import/export functionality, please ensure:

  1. The Core field is properly serialized/deserialized during project export/import
  2. Existing projects without the Core field are handled gracefully
  3. End-to-end tests cover the Core field behavior

Let's verify the test coverage:

✅ Verification successful

Let me gather more information about the Core field testing by checking the test implementations in detail.


Based on the test coverage results, I can now generate the final response:

Core field is properly tested across different layers

The Core field has comprehensive test coverage:

  • E2E tests verify both default (false) and explicit (true) Core values during project creation
  • Integration tests in project_test.go include Core field validation
  • The import/export functionality includes Core field in the test cases
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check test coverage for project-related operations
echo "Checking test coverage for project operations..."

# Look for project-related test files
fd "project.*test\.go$"

# Check for Core field testing
rg "TestCreate.*Project|TestExport.*Project|TestImport.*Project" -A 10

Length of output: 2193


Script:

#!/bin/bash
# Check for Core field testing in project tests
echo "Checking Core field testing in project tests..."

# Search for Core field in test files
rg "Core.*:.*true|Core.*:.*false" server/e2e/gql_project_test.go server/internal/usecase/interactor/project_test.go -B 5 -A 5

# Check test cases for project creation and import
rg "mutation CreateProject|mutation ImportProject" server/e2e/gql_project_test.go -B 5 -A 10

# Check project model tests
rg "Core" server/pkg/project/project_test.go -A 5 -B 5

Length of output: 2879


43-43: Verify the Core field implementation and its impact

The addition of the Core field to CreateProjectParam raises several considerations:

  1. The field is only added to project creation but not to project updates, which could lead to inconsistency in how the Core flag is managed throughout a project's lifecycle.
  2. There's a potential gap between the PR objectives (which focus on asset visualizer flags) and this change to project core functionality.

Let's verify the implementation consistency:

Consider the following architectural recommendations:

  1. If the Core flag is meant to be immutable, document this decision.
  2. If it should be mutable, add support in the UpdateProject mutation.
  3. Clarify the relationship between this Core flag and the asset visualizer functionality mentioned in the PR objectives.
server/e2e/gql_project_test.go (1)

Line range hint 21-85: Verify alignment with PR objectives

The PR objectives mention adding a "visualizer flag", but the test changes are implementing a "core" field. This seems to be a discrepancy that needs clarification.

The test implementation itself looks good, covering both:

  1. Default core value (false)
  2. Explicit core value (true)

Let's verify if there are any visualizer-related changes that should be included:

✅ Verification successful

Let me gather more context about the PR objectives and visualizer changes:


Let me check the changelog and readme for context about these changes:


Let me check the actual Project struct implementation:


Let me check the test file and GraphQL schema for the core field:


Based on the evidence gathered, I can now provide a final response:

The test implementation is correct and matches the schema

The test file correctly verifies the core field functionality:

  1. Tests default value (false) when creating a project without specifying core
  2. Tests explicit value (true) when creating a project with core specified
  3. The field is properly defined in the GraphQL schema as a Boolean
  4. The field exists in the Project struct implementation

The PR objectives mentioning "visualizer flag" likely refer to a different change, as the visualizer field is already present and required in the schema (visualizer: Visualizer!). The core field changes appear to be an independent feature.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for visualizer-related changes in the codebase
rg -g '!{node_modules,dist,build}/*' -l 'visualizer.*flag|flag.*visualizer'

# Search for related schema changes
fd -g '*.graphql' -x cat {} | grep -A 5 -B 5 'visualizer'

Length of output: 879


Script:

#!/bin/bash
# Check the PR description or recent commits for context
gh pr view --json title,body

# Look for visualizer-related changes in the test file
rg -C 5 "visualizer" server/e2e/gql_project_test.go

# Check if there are any other test files with visualizer changes
fd -g '*_test.go' -x rg -l "visualizer" {}

Length of output: 2259


Script:

#!/bin/bash
# Check README for visualizer flag mentions
cat server/README.md | grep -A 5 -B 5 "visualizer.*flag\|flag.*visualizer"

# Check CHANGELOG for recent changes
cat CHANGELOG.md | grep -A 5 -B 5 "visualizer\|core"

# Check the actual implementation of CreateProject
ast-grep --pattern 'type Project struct {
  $$$
  Visualizer $$$
  Core $$$
  $$$
}'

Length of output: 131549


Script:

#!/bin/bash
# Check Project struct implementation
ast-grep --pattern 'type Project struct {
  $$$
}'

# Check if there are any tests related to the core field
rg -A 5 -B 5 "core.*Project" server/pkg/project/project_test.go

Length of output: 7173


Script:

#!/bin/bash
# Check test file for core field
cat server/e2e/gql_project_test.go

# Check GraphQL schema for core field
fd -g '*.graphql' -x cat {} | grep -A 5 -B 5 'core:'

Length of output: 14268

server/internal/usecase/interactor/project.go (1)

607-607: LGTM on Core field import handling

The Core field is properly handled during project import, consistent with other field imports.

server/internal/usecase/interactor/scene.go (3)

128-130: LGTM: Consistent visualizer selection logic across operations.

The changes maintain consistency in visualizer selection logic between scene creation and import operations, using Core() to determine the appropriate visualizer type.

Also applies to: 809-811


632-632: LGTM: Aligned BuildResult parameters with core flag changes.

The BuildResult parameter has been updated to use Core(), maintaining consistency with the rest of the codebase.


128-130: Verify impact on existing scenes.

The change from CoreSupport() to Core() might affect how existing scenes are handled. Please ensure that:

  1. Existing scenes maintain their visualizer settings
  2. The migration path for existing data is clear

Also applies to: 632-632, 809-811

server/e2e/gql_storytelling_test.go (1)

36-36: Verify default value for core flag

The core flag is hardcoded to true. Consider if this is the intended default value, as it might affect existing data.

✅ Verification successful

Let me gather more context about the core flag usage by checking its definition and implementation.


Core flag is correctly set to true for storytelling

Based on the codebase analysis, setting core: true in the storytelling test is correct and consistent with the implementation. The core flag is intentionally set to true in the storytelling builder (server/pkg/storytelling/story_bulider.go) and this test is verifying that behavior. This is not a default value that needs verification, but rather a deliberate implementation detail of the storytelling feature.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other instances where the core flag is set
rg "core\": (?:true|false)" --type go

Length of output: 308


Script:

#!/bin/bash
# Search for core flag definition and type declarations
ast-grep --pattern 'type $_ struct {
  $$$
  Core $_
  $$$
}'

# Search for any core-related constants or configurations
rg "core.*=|const.*core" --type go -i

# Check for core flag in test setup or assertions
rg "core.*assert|assert.*core" --type go -i

Length of output: 13260

server/internal/infrastructure/mongo/mongodoc/asset.go Outdated Show resolved Hide resolved
server/internal/adapter/gql/gqlmodel/convert_project.go Outdated Show resolved Hide resolved
server/gql/project.graphql Outdated Show resolved Hide resolved
server/internal/infrastructure/mongo/mongodoc/project.go Outdated Show resolved Hide resolved
server/e2e/gql_asset_test.go Outdated Show resolved Hide resolved
server/e2e/gql_asset_test.go Show resolved Hide resolved
server/pkg/storytelling/story.go Outdated Show resolved Hide resolved
server/pkg/project/builder_test.go Outdated Show resolved Hide resolved
Copy link

@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: 1

🧹 Outside diff range and nitpick comments (1)
server/e2e/gql_asset_test.go (1)

103-141: Remove unnecessary __typename fields from the query

The query includes __typename fields which are not used in the tests and add unnecessary overhead to the response. Consider removing them unless they serve a specific purpose.

 const GetAssetsQuery = `query GetAssets($teamId: ID!, $pagination: Pagination, $keyword: String, $sort: AssetSort) {
     assets(teamId: $teamId, pagination: $pagination, keyword: $keyword, sort: $sort) {
       edges {
         cursor
         node {
           id
           teamId
           name
           size
           url
           createdAt
           contentType
           core
-          __typename
         }
-        __typename
       }
       nodes {
         id
         teamId
         name
         size
         url
         createdAt
         contentType
         core
-        __typename
       }
       pageInfo {
         endCursor
         hasNextPage
         hasPreviousPage
         startCursor
-        __typename
       }
       totalCount
-      __typename
     }
   }`
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6f0ea74 and 47c6a84.

📒 Files selected for processing (1)
  • server/e2e/gql_asset_test.go (1 hunks)
🔇 Additional comments (1)
server/e2e/gql_asset_test.go (1)

1-166: Verify the impact of flag name change and data migration needs

The PR objectives mention a "visualizer" flag, but the implementation uses "core". Let's verify the consistency across the codebase and identify data migration needs.

✅ Verification successful

The previous results show that the core flag is consistently used across the codebase, but we need to verify the schema definitions and any potential migration needs. The new script will help us confirm if there are any schema inconsistencies or if migration files are needed for the flag change.


Based on the results, I can now generate the final response:

The core flag is consistently used across the codebase

The codebase analysis shows that:

  • The core flag is consistently used in GraphQL schema (server/gql/asset.graphql)
  • The flag is properly implemented in the Asset model and MongoDB queries
  • There's no evidence of a "visualizer" flag in the asset-related code
  • The MongoDB query includes a migration-friendly condition: {"$or": [{"core": true}, {"core": {"$exists": false}}]}

The implementation is correct and consistent. The MongoDB query already handles the case where the flag might not exist in older documents, effectively treating them as core: true.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for inconsistencies between "visualizer" and "core" flags

# Check for "visualizer" usage in GraphQL schema files
echo "Checking GraphQL schema files for 'visualizer' field..."
rg -l "visualizer.*:.*Boolean" --type graphql

# Check for "core" usage in GraphQL schema files
echo "Checking GraphQL schema files for 'core' field..."
rg -l "core.*:.*Boolean" --type graphql

# Check for existing database queries using either flag
echo "Checking Go files for database queries..."
rg -B2 -A2 "(?:visualizer|core).*(?:true|false)" --type go

# Check for GraphQL queries/mutations using either flag
echo "Checking for GraphQL operations..."
rg -B2 -A2 "(?:visualizer|core).*:.*(?:true|false)" --type graphql

Length of output: 7443


Script:

#!/bin/bash
# Let's check for GraphQL schema files with a more generic approach
echo "Checking for GraphQL schema files..."
fd -e graphql -e gql

# Then check for schema definitions
echo "Checking schema content..."
fd -e graphql -e gql --exec cat {}

# Check for database schema or migration files
echo "Checking for migration files..."
fd -g "*migration*"

# Check for asset-related model definitions
echo "Checking asset model definitions..."
rg -B5 -A5 "type Asset struct" --type go

Length of output: 45905

server/e2e/gql_asset_test.go Outdated Show resolved Hide resolved
@hexaforce hexaforce changed the title feat(server): add Visualizer flag feat(server): Add core to Asset and rename coreSupport to core in Project Nov 21, 2024
@hexaforce hexaforce changed the title feat(server): Add core to Asset and rename coreSupport to core in Project feat(server): Add coreSupport to Asset Nov 22, 2024
Copy link

@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: 4

🧹 Outside diff range and nitpick comments (2)
server/e2e/gql_asset_test.go (2)

103-141: Update query to use 'core' and reduce repetition

The GraphQL query needs improvements:

  1. Rename coreSupport to core
  2. Use fragments to reduce field repetition between edges.node and nodes
+const AssetFragment = `
+  fragment AssetFields on Asset {
+    id
+    teamId
+    name
+    size
+    url
+    createdAt
+    contentType
+    core
+    __typename
+  }
+`
+
 const GetAssetsQuery = `query GetAssets($teamId: ID!, $pagination: Pagination, $keyword: String, $sort: AssetSort) {
     assets(teamId: $teamId, pagination: $pagination, keyword: $keyword, sort: $sort) {
       edges {
         cursor
         node {
-          id
-          teamId
-          name
-          size
-          url
-          createdAt
-          contentType
-          coreSupport
-          __typename
+          ...AssetFields
         }
         __typename
       }
       nodes {
-        id
-        teamId
-        name
-        size
-        url
-        createdAt
-        contentType
-        coreSupport
-        __typename
+        ...AssetFields
       }
       pageInfo {
         endCursor
         hasNextPage
         hasPreviousPage
         startCursor
         __typename
       }
       totalCount
       __typename
     }
-  }`
+  }
+  ${AssetFragment}`

143-166: Improve asset retrieval helper with options and error handling

The helper function needs improvements:

  1. Make pagination and sorting parameters configurable
  2. Add response error handling
+type AssetQueryOptions struct {
+    First     int
+    SortField string
+    SortDir   string
+}
+
+type AssetQueryOption func(*AssetQueryOptions)
+
+func WithFirst(first int) AssetQueryOption {
+    return func(o *AssetQueryOptions) {
+        o.First = first
+    }
+}
+
+func WithSort(field, direction string) AssetQueryOption {
+    return func(o *AssetQueryOptions) {
+        o.SortField = field
+        o.SortDir = direction
+    }
+}
+
-func getAssets(e *httpexpect.Expect, teamId string) *httpexpect.Value {
+func getAssets(e *httpexpect.Expect, teamId string, opts ...AssetQueryOption) *httpexpect.Value {
+    options := AssetQueryOptions{
+        First:     20,
+        SortField: "DATE",
+        SortDir:   "DESC",
+    }
+    
+    for _, opt := range opts {
+        opt(&options)
+    }
+
     requestBody := GraphQLRequest{
         OperationName: "GetAssets",
         Query:         GetAssetsQuery,
         Variables: map[string]any{
             "teamId": teamId,
             "pagination": map[string]any{
-                "first": 20,
+                "first": options.First,
             },
             "sort": map[string]string{
-                "direction": "DESC",
-                "field":     "DATE",
+                "direction": options.SortDir,
+                "field":     options.SortField,
             },
         },
     }
-    return e.POST("/api/graphql").
+    response := e.POST("/api/graphql").
         WithHeader("Origin", "https://example.com").
         WithHeader("X-Reearth-Debug-User", uID.String()).
         WithHeader("Content-Type", "application/json").
         WithJSON(requestBody).
         Expect().
         Status(http.StatusOK).
         JSON()
+
+    // Validate response structure
+    response.Path("$.errors").Absent()
+    return response
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 47c6a84 and 91e4d2f.

📒 Files selected for processing (16)
  • server/e2e/gql_asset_test.go (1 hunks)
  • server/gql/asset.graphql (3 hunks)
  • server/internal/adapter/gql/generated.go (12 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_asset.go (1 hunks)
  • server/internal/adapter/gql/gqlmodel/models_gen.go (2 hunks)
  • server/internal/adapter/gql/resolver_mutation_asset.go (1 hunks)
  • server/internal/adapter/gql/resolver_mutation_property.go (1 hunks)
  • server/internal/infrastructure/memory/asset.go (1 hunks)
  • server/internal/infrastructure/mongo/asset.go (2 hunks)
  • server/internal/infrastructure/mongo/mongodoc/asset.go (3 hunks)
  • server/internal/usecase/interactor/asset.go (1 hunks)
  • server/internal/usecase/interactor/asset_test.go (2 hunks)
  • server/internal/usecase/interfaces/asset.go (1 hunks)
  • server/pkg/asset/asset.go (2 hunks)
  • server/pkg/asset/asset_test.go (4 hunks)
  • server/pkg/asset/builder.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (15)
  • server/gql/asset.graphql
  • server/internal/adapter/gql/generated.go
  • server/internal/adapter/gql/gqlmodel/convert_asset.go
  • server/internal/adapter/gql/gqlmodel/models_gen.go
  • server/internal/adapter/gql/resolver_mutation_asset.go
  • server/internal/adapter/gql/resolver_mutation_property.go
  • server/internal/infrastructure/memory/asset.go
  • server/internal/infrastructure/mongo/asset.go
  • server/internal/infrastructure/mongo/mongodoc/asset.go
  • server/internal/usecase/interactor/asset.go
  • server/internal/usecase/interactor/asset_test.go
  • server/internal/usecase/interfaces/asset.go
  • server/pkg/asset/asset.go
  • server/pkg/asset/asset_test.go
  • server/pkg/asset/builder.go

server/e2e/gql_asset_test.go Show resolved Hide resolved
server/e2e/gql_asset_test.go Show resolved Hide resolved
server/e2e/gql_asset_test.go Show resolved Hide resolved
server/e2e/gql_asset_test.go Show resolved Hide resolved
@hexaforce hexaforce merged commit d119c43 into main Nov 22, 2024
22 checks passed
@hexaforce hexaforce deleted the feat/exclusion-classic-assets branch November 22, 2024 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants