Skip to content

feat(server): item fields normalization #1095

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

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

Conversation

yk-eukarya
Copy link
Contributor

@yk-eukarya yk-eukarya commented Mar 11, 2024

Summary by CodeRabbit

  • Refactor
    • Improved handling and embedding of assets and metadata for items, resulting in more consistent and streamlined item responses.
    • Unified schema management for items, simplifying field extraction and schema lookups.
    • Updated API conversion logic for assets, items, and events to use a new context-based approach, enhancing maintainability.
    • Renamed and reorganized several internal functions for clarity and consistency.
  • Bug Fixes
    • Standardized field representations and ordering in item-related API responses and tests.
    • Improved test assertions for item fields, including asset handling and metadata validation.
  • Chores
    • Removed unused functions and obsolete code related to item referencing.
    • Updated tests to align with new function signatures and improved internal logic.

@yk-eukarya yk-eukarya self-assigned this Mar 11, 2024
Copy link

netlify bot commented Mar 11, 2024

Deploy Preview for reearth-cms canceled.

Name Link
🔨 Latest commit e0a6353
🔍 Latest deploy log https://app.netlify.com/sites/reearth-cms/deploys/67ff8a0934e8500008c7a7af

@yk-eukarya yk-eukarya requested a review from rot1024 as a code owner March 21, 2024 07:26
# Conflicts:
#	go.work.sum
#	server/e2e/integration_item_test.go
#	server/internal/adapter/gql/gqlmodel/convert_item.go
#	server/internal/adapter/gql/loader_item.go
#	server/internal/adapter/gql/resolver_mutation_item.go
#	server/internal/adapter/integration/convert.go
#	server/internal/adapter/integration/item.go
#	server/internal/adapter/publicapi/api.go
#	server/pkg/integrationapi/asset.go
#	server/pkg/item/item.go
#	server/pkg/item/reference_test.go
#	server/pkg/schema/package.go
Copy link
Contributor

coderabbitai bot commented Apr 16, 2025

Walkthrough

This change is a comprehensive refactor of item and asset handling across the server, integration API, and GraphQL adapter layers. It introduces a new ConvertContext abstraction to centralize asset and item resolution, replaces various conversion and embedding functions with new context-aware versions, and updates function signatures throughout the stack to use schema packages and the new context. Test code and field assertions are updated to support more flexible value types and new asset field expectations. Several obsolete helper functions and files are removed, and the codebase is updated for consistency in naming and parameter usage.

Changes

File(s) Change Summary
server/e2e/integration_item_project_test.go, server/e2e/integration_item_test.go Updated tests to expect fields as map[string]any, added asset-type fields with nil values, adjusted field ordering, and improved assertion logic.
server/internal/adapter/gql/gqlmodel/convert_item.go, server/internal/adapter/gql/gqlmodel/convert_item_test.go, server/internal/adapter/gql/loader_item.go, server/internal/adapter/gql/resolver_item.go Refactored to use schema packages instead of separate schema/group schema lists, simplified field extraction, and updated all relevant function signatures and usages.
server/internal/adapter/integration/item.go Refactored asset and metadata loading by introducing a loader/context container, removed multiple helper functions, and streamlined integration item construction.
server/internal/adapter/integration/convert.go Commented out assignments to the Key field in ItemFieldParam construction.
server/internal/adapter/integration/schema.go Updated field type construction to use NewValueType instead of ToValueType.
server/internal/adapter/publicapi/api.go Renamed public API handler functions for clarity and consistency.
server/internal/infrastructure/aws/webhook.go, server/internal/infrastructure/gcp/webhook.go Updated calls to integrationapi.NewEventWith to remove the unused string parameter.
server/pkg/integrationapi/asset.go, server/pkg/integrationapi/asset_test.go Renamed conversion functions to use New prefix, updated parameter names, and replaced hardcoded status strings with constants.
server/pkg/integrationapi/convert.go, server/pkg/integrationapi/convert_context.go, server/pkg/integrationapi/event.go, server/pkg/integrationapi/event_test.go, server/pkg/integrationapi/item.go, server/pkg/integrationapi/schema.go, server/pkg/integrationapi/value.go, server/pkg/integrationapi/value_test.go Introduced ConvertContext and Loaders types, refactored all conversion logic to use context and schema packages, updated or removed obsolete functions, and unified naming conventions.
server/pkg/item/item.go, server/pkg/item/item_test.go Changed Item.fields to a custom Fields type, added NormalizedFields method, and updated tests accordingly.
server/pkg/item/reference.go, server/pkg/item/reference_test.go Deleted obsolete reference checking function and its test.
server/pkg/schema/package.go Refactored Package.Field to delegate to a new unified field lookup method.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GraphQL
    participant IntegrationAPI
    participant ConvertContext
    participant AssetService
    participant ItemService

    Client->>GraphQL: Create/Update/Fetch Item
    GraphQL->>IntegrationAPI: ToItem/ToVersionedItem (with schema package, context)
    IntegrationAPI->>ConvertContext: ResolveAsset/ResolveReferencedItem
    ConvertContext->>AssetService: Load assets by ID (if needed)
    ConvertContext->>ItemService: Load referenced/meta items by ID (if needed)
    IntegrationAPI-->>GraphQL: Item/VersionedItem (with embedded assets/items)
    GraphQL-->>Client: Response with item and fields
Loading

Possibly related PRs

Poem

Hopping through code with a context anew,
Assets and items, now neatly in view.
Old helpers retired, new loaders at play,
Fields more flexible—nil assets okay!
From schemas to tests, the changes cascade,
A garden of context, robustly remade.
🐇✨ Cheers to the code, now smarter and spry!

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (3)
server/internal/adapter/integration/item.go (3)

145-146: Same asset embedding approach.
The pattern matches lines 39-40. The comment regarding afEmbed usage applies here as well.


152-152: Refactored call to NewVersionedItem.
Identical to line 46 comment.


402-403: Embedding assets on single item retrieval.
Identical pattern to other calls; same observation applies concerning afEmbed.

🧹 Nitpick comments (10)
server/pkg/integrationapi/schema.go (1)

39-42: Passing nil values for the new context-based approach.

The function now passes nil for the schema package and convert context parameters to NewItem and NewVersionedItem. This is part of the refactoring that centralizes asset and item loading through the ConvertContext.

Consider adding a comment explaining why nil values are acceptable here, to improve code readability.

-		Item: NewItem(i.Item, nil, nil),
+		Item: NewItem(i.Item, nil, nil), // Schema and ConvertContext not needed for this conversion
 		ReferencedItems: lo.Map(i.ReferencedItems, func(itm *version.Value[*item.Item], _ int) *VersionedItem {
-			return lo.ToPtr(NewVersionedItem(itm, nil, nil))
+			return lo.ToPtr(NewVersionedItem(itm, nil, nil)) // Schema and ConvertContext not needed for this conversion
server/internal/adapter/gql/loader_item.go (1)

91-91: Find all versions
Retrieving all versions is correct. Consider handling large version histories with pagination if the version count grows.

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

51-91: Introduce NormalizedFields for schema-based expansion
This method constructs a comprehensive field list matching the schema package. Key observations:

  • It appends empty fields for schema entries that the item lacks, ensuring completeness.
  • Group fields are expanded if they contain valid group IDs. This deeply normalizes nested fields, which is beneficial for a consistent data shape but could be expensive if used frequently on large items.
  • The code halts appending more group fields if Multiple() is false, which is correct.

Possible improvement:

  • Validate that GroupSchema(gID) exists (i.e., groupSchemas[gID]) to avoid nil returns in edge cases.
    Otherwise, this is a strong approach to unify item fields with the schema’s structure.
 if sp == nil {
     return nil
 }
+if sp.GroupSchema(gID) == nil {
+    // Optionally handle or log the missing group schema rather than silently ignore
+}
server/pkg/integrationapi/value.go (2)

52-52: Consider adding missing reverse mapping for ValueTypeCheckbox.

Currently, the function NewValueType correctly maps value.TypeCheckbox to ValueTypeCheckbox, but its counterpart function FromValueType does not handle ValueTypeCheckbox. This asymmetry can lead to incomplete conversions.

 func FromValueType(t *ValueType) value.Type {
     if t == nil {
         return ""
     }
     switch *t {
+    case ValueTypeCheckbox:
+        return value.TypeCheckbox
     ...
 }

102-105: Ensure ResolveAsset handles all error cases.

The code calls cc.ResolveAsset(aid) without apparent fallback if it returns nil or encounters an error. Consider adding logic to handle the case where the asset cannot be resolved (e.g., returning a placeholder value or an explicit error).

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

33-33: Check for possible nil returns from sp.Schema().

If sp.Schema() is ever nil, i.GetTitle(nil) may produce unexpected behavior. Verify that the rest of the system guarantees a non-nil schema.

server/pkg/integrationapi/item.go (1)

13-41: Unifying schema usage with ConvertContext.

NewVersionedItem effectively resolves metadata items via cc.ResolveMetaItem and constructs field sets with NewFields. However, line 24 passes nil as the ConvertContext when creating the schema package for meta fields. This might skip asset or item embedding in metadata fields. Consider passing the same cc or clarifying why a nil context is acceptable.

server/pkg/integrationapi/convert_context.go (2)

30-52: Conditional loading logic looks solid.
The constructor properly initializes and then conditionally loads referenced items, meta items, and assets. However, note that embedAssetsFiles is passed in yet never stored or used (via afEmbed).

-func NewCC(il item.VersionedList, embedAssets, embedAssetsFiles bool, l Loaders) (*ConvertContext, error) {
+func NewCC(il item.VersionedList, embedAssets, embedAssetsFiles bool, l Loaders) (*ConvertContext, error) {
     cc := &ConvertContext{
         aFiles:   make(map[asset.ID]*asset.File),
         aBaseURL: l.AssetURL,
         aEmbed:   embedAssets,
-        // Possibly missing usage for embedAssetsFiles in the below fields
         loaders:  l,
     }
     ...
 }

68-88: Reference item loading logic.
The approach for finding all reference-type fields and loading the corresponding items is clear. Consider applying deduplication (as with assets) if needed to reduce repeated lookups, but it might be fine if the loader itself handles it.

server/internal/adapter/integration/item.go (1)

454-457: Clear logic in shouldEmbedAsset.
This function adequately distinguishes normal vs file-level embedding. However, the second return value is unused down the line.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e369267 and e0a6353.

📒 Files selected for processing (27)
  • server/e2e/integration_item_project_test.go (2 hunks)
  • server/e2e/integration_item_test.go (11 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_item.go (3 hunks)
  • server/internal/adapter/gql/gqlmodel/convert_item_test.go (5 hunks)
  • server/internal/adapter/gql/loader_item.go (5 hunks)
  • server/internal/adapter/gql/resolver_item.go (5 hunks)
  • server/internal/adapter/integration/convert.go (2 hunks)
  • server/internal/adapter/integration/item.go (6 hunks)
  • server/internal/adapter/integration/schema.go (4 hunks)
  • server/internal/adapter/publicapi/api.go (3 hunks)
  • server/internal/infrastructure/aws/webhook.go (1 hunks)
  • server/internal/infrastructure/gcp/webhook.go (1 hunks)
  • server/pkg/integrationapi/asset.go (3 hunks)
  • server/pkg/integrationapi/asset_test.go (5 hunks)
  • server/pkg/integrationapi/convert.go (1 hunks)
  • server/pkg/integrationapi/convert_context.go (1 hunks)
  • server/pkg/integrationapi/event.go (1 hunks)
  • server/pkg/integrationapi/event_test.go (2 hunks)
  • server/pkg/integrationapi/item.go (1 hunks)
  • server/pkg/integrationapi/schema.go (1 hunks)
  • server/pkg/integrationapi/value.go (2 hunks)
  • server/pkg/integrationapi/value_test.go (1 hunks)
  • server/pkg/item/item.go (3 hunks)
  • server/pkg/item/item_test.go (2 hunks)
  • server/pkg/item/reference.go (0 hunks)
  • server/pkg/item/reference_test.go (0 hunks)
  • server/pkg/schema/package.go (1 hunks)
💤 Files with no reviewable changes (2)
  • server/pkg/item/reference_test.go
  • server/pkg/item/reference.go
🧰 Additional context used
🧬 Code Graph Analysis (11)
server/pkg/integrationapi/value_test.go (1)
server/pkg/integrationapi/value.go (1)
  • NewValueType (52-91)
server/pkg/integrationapi/asset_test.go (1)
server/pkg/integrationapi/asset.go (3)
  • NewAssetFile (55-81)
  • NewAssetArchiveExtractionStatus (35-53)
  • NewPreviewType (83-107)
server/internal/infrastructure/aws/webhook.go (1)
server/pkg/integrationapi/event.go (2)
  • NewEventWith (41-67)
  • Event (11-18)
server/pkg/integrationapi/schema.go (2)
server/pkg/item/item.go (2)
  • ItemModelSchema (280-287)
  • Item (16-31)
server/pkg/integrationapi/item.go (2)
  • NewItem (73-84)
  • NewVersionedItem (13-41)
server/internal/adapter/integration/schema.go (1)
server/pkg/integrationapi/value.go (1)
  • NewValueType (52-91)
server/internal/adapter/gql/gqlmodel/convert_item_test.go (2)
server/pkg/schema/package.go (1)
  • NewPackage (15-22)
server/internal/adapter/gql/gqlmodel/convert_item.go (2)
  • ToItem (12-36)
  • ToVersionedItem (51-68)
server/internal/adapter/gql/resolver_item.go (4)
server/internal/usecase/interactor/schema.go (1)
  • Schema (17-20)
server/internal/usecase/interfaces/item.go (1)
  • Item (127-151)
server/internal/adapter/gql/gqlmodel/convert_item.go (1)
  • ToItem (12-36)
server/internal/usecase/interfaces/model.go (1)
  • Model (62-78)
server/pkg/item/item.go (10)
server/pkg/item/fields.go (1)
  • Fields (10-10)
server/pkg/item/id.go (4)
  • ThreadID (15-15)
  • UserID (16-16)
  • IntegrationID (17-17)
  • ID (8-8)
server/pkg/schema/package.go (1)
  • Package (8-13)
server/pkg/schema/schema.go (1)
  • Schema (15-21)
server/pkg/item/field.go (2)
  • Field (9-13)
  • NewField (15-24)
server/pkg/value/multiple.go (2)
  • NewMultiple (13-25)
  • Multiple (8-11)
server/pkg/value/type.go (1)
  • Type (3-3)
server/pkg/value/group.go (1)
  • TypeGroup (8-8)
server/pkg/schema/type_property.go (1)
  • TypePropertyMatch (34-53)
server/pkg/schema/field_group.go (1)
  • FieldGroup (7-9)
server/pkg/integrationapi/convert_context.go (7)
server/pkg/asset/map.go (1)
  • Map (5-5)
server/pkg/item/list.go (1)
  • VersionedList (34-34)
server/pkg/id/id.go (1)
  • ItemID (178-178)
server/pkg/item/item.go (1)
  • Versioned (33-33)
server/pkg/item/fields.go (1)
  • Fields (10-10)
server/pkg/value/reference.go (1)
  • TypeReference (8-8)
server/pkg/integrationapi/asset.go (1)
  • NewAsset (8-33)
server/e2e/integration_item_test.go (1)
server/pkg/id/key.go (1)
  • NewKey (26-29)
server/pkg/integrationapi/event.go (2)
server/pkg/asset/asset.go (1)
  • URLResolver (26-26)
server/pkg/integrationapi/convert.go (1)
  • New (17-45)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: ci-server / test
  • GitHub Check: ci-server / lint
🔇 Additional comments (82)
server/pkg/integrationapi/value_test.go (1)

219-219: Clean function rename alignment.

The change from ToValueType to NewValueType aligns with the broader refactoring in the integration API where conversion functions were renamed from To* to New* prefixes for more consistent naming conventions.

server/internal/infrastructure/aws/webhook.go (1)

24-24: Updated function call matches new signature.

The empty string parameter has been correctly removed from the NewEventWith call to match the updated function signature. This change properly aligns with the refactored API where this parameter is no longer needed.

server/pkg/item/item_test.go (2)

86-86: Type change from []*Field to Fields.

The test assertion has been updated to use the new Fields type instead of a raw slice of pointers to Field, which aligns with the refactoring of the Item struct's field type.


101-101: Type change from []*Field to Fields.

The test assertion has been updated to use the new Fields type instead of a raw slice of pointers to Field, which aligns with the refactoring of the Item struct's field type.

server/internal/adapter/integration/convert.go (2)

125-126: Key field assignment commented out.

The Key field assignment is intentionally commented out as part of the field normalization refactoring. This aligns with the introduction of the ConvertContext and normalized field representations where explicit Key setting may no longer be necessary.

Verify that the downstream code that consumes these ItemFieldParam objects doesn't rely on the Key field being set at this point, and that it's either not needed or set elsewhere in the refactored code path.


154-155: Key field assignment commented out.

The Key field assignment is intentionally commented out as part of the field normalization refactoring. This aligns with the introduction of the ConvertContext and normalized field representations where explicit Key setting may no longer be necessary.

Verify that the downstream code that consumes these ItemFieldParam objects doesn't rely on the Key field being set at this point, and that it's either not needed or set elsewhere in the refactored code path.

server/internal/adapter/integration/schema.go (1)

115-115: Function calls renamed from ToValueType to NewValueType

These changes are part of a broader refactoring effort to rename conversion functions from To* to New* across the integration API. The function behavior remains the same, but names are now more consistent.

Also applies to: 176-176, 227-227, 294-294

server/internal/infrastructure/gcp/webhook.go (1)

24-24: Simplified function signature for NewEventWith

The empty string parameter has been removed from the NewEventWith call, reflecting the updated function signature in the integration API that no longer needs this parameter. This change simplifies the API surface while preserving functionality.

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

20-20: Function calls renamed from ToAssetFile to NewAssetFile

These changes align the test code with the renaming of the asset conversion functions in the codebase. The To* prefix has been standardized to New* prefix while maintaining the same function behavior.

Also applies to: 45-45, 54-54


160-160: Function call renamed from ToAssetArchiveExtractionStatus to NewAssetArchiveExtractionStatus

This change aligns the test code with the renaming pattern of asset conversion functions from To* to New* in the integration API package.


227-227: Function call renamed from ToPreviewType to NewPreviewType

This change is part of the consistent renaming pattern from To* to New* for conversion functions in the integration API package.

server/internal/adapter/gql/gqlmodel/convert_item_test.go (2)

30-30: Updated test to use schema.Package abstraction

The test now creates a schema package and passes it to ToItem, aligning with the refactored function signature that uses a single *schema.Package parameter instead of separate schema objects. This approach centralizes schema handling and simplifies the API.

Also applies to: 82-82


134-134: Updated ToVersionedItem test to use schema.Package

Similar to the ToItem test changes, these updates adapt the tests to use the new schema.Package abstraction, which encapsulates all schema-related information in a single container. This provides a more unified approach to schema handling across the GraphQL adapter layer.

Also applies to: 151-151, 160-160

server/pkg/integrationapi/event_test.go (2)

83-84: Parameter removal aligns with refactored method signatures.

The removal of the version string parameter (v) from the New function call is consistent with the broader refactoring of the integration API conversion logic.


163-163: Test updated to match new function signature.

The call to NewEventWith now omits the version string parameter, correctly reflecting the updated method signature that no longer requires this parameter.

server/pkg/integrationapi/schema.go (1)

37-37: Function signature simplified by removing the assets parameter.

The NewItemModelSchema function has been simplified by removing the assets parameter, which is consistent with the introduction of the new ConvertContext approach that centralizes asset and item resolution.

server/e2e/integration_item_project_test.go (2)

157-168: Test expectations updated to reflect new field structure.

The test has been correctly updated to:

  1. Use map[string]any instead of map[string]string to accommodate more flexible value types
  2. Include a new asset field with a nil value, reflecting the updated item field normalization

This ensures the test validates the behavior after the field normalization changes.


189-200: Consistent update to second assertion.

The changes to this assertion match the pattern used in the first one, maintaining consistency in how asset fields are represented.

server/internal/adapter/gql/resolver_item.go (4)

161-164: Simplified schema retrieval using FindByModel.

This change improves the code by fetching a single schema package by model ID instead of multiple schemas and group schemas. This aligns with the broader refactoring to unify schema handling under the schema.Package abstraction.


176-177: Simplified item conversion with schema package.

The call to ToItem now uses the schema package directly, which streamlines the conversion by avoiding the need to pass multiple schema-related parameters.


207-210: Consistent schema retrieval approach.

This change follows the same pattern as in CreateItem, maintaining consistency in how schemas are retrieved across resolver methods.


213-214: Simplified item conversion with schema package.

Same improvement as in the CreateItem resolver, maintaining consistency.

server/pkg/integrationapi/convert.go (4)

17-17: Function signature improvement: Removed unused parameter

The function signature has been simplified by removing the unused v string parameter, as indicated by the comment on line 18. This improves code clarity.


21-21: Updated function call to match new signature

This call correctly adapts to the updated signature of NewEventWith that no longer takes a string parameter.


25-25: Function renaming for consistency

The function has been renamed from ToAssetFile to NewAssetFile to follow a more consistent naming convention for factory methods (New* instead of To*).


29-29: Simplified function calls

The function calls to NewVersionedItem and NewItemModelSchema have been simplified by removing unnecessary parameters, which improves readability.

Also applies to: 31-31

server/internal/adapter/publicapi/api.go (2)

36-37: Improved handler naming convention

The handler functions have been renamed from PublicApi* to more concise names that follow idiomatic Go naming conventions. This improves code readability and maintainability.


40-40: Consistent function naming

Functions have been renamed from PublicApi* to follow lowercase naming conventions (itemOrAssetHandler, itemListHandler, assetHandler). This is more aligned with Go's idiomatic style where public API prefixes aren't needed in internal function names.

Also applies to: 64-64, 115-115

server/pkg/schema/package.go (1)

79-81: Refactored to reduce code duplication

The Field method now delegates to the more flexible FieldByIDOrKey method, which consolidates field lookup logic. This improves maintainability and reduces code duplication.

This refactoring aligns with the broader changes to unify schema handling under the schema.Package abstraction, making the code more consistent across the codebase.

server/pkg/integrationapi/event.go (2)

41-41: Simplified function signature

The NewEventWith function's signature has been simplified by removing the unused v string parameter, making the API cleaner.


46-46: Updated call to reflect parameter removal

The call to New has been updated to match its new signature without the v parameter. This maintains consistency with the changes in convert.go.

server/internal/adapter/gql/loader_item.go (11)

13-13: Imported log from reearthx
No immediate concerns. Ensure logging is appropriately leveled and does not cause excessive overhead.


41-41: Retrieve items by their IDs
Fetching items using FindByIDs is straightforward. Check whether bulk-fetching large ID lists can handle concurrency or pagination if the dataset grows significantly.


46-48: Graceful exit for empty result
This check avoids downstream nil pointer issues. Good defensive programming.


50-50: Single schema retrieval
Fetching a single sp based on the first item's model aligns with the new consolidated schema approach.


55-56: Mapping items to GraphQL
Passing a single schema.Package to gqlmodel.ToItem is consistent with the updated unification strategy.


75-81: Versioned item schema retrieval
Analogous logic to the “Fetch” method for versioned items. This maintains consistency. No major issues noted.


96-98: Return empty if versions are missing
Same robust pattern for nil checks as in “Fetch.” This prevents runtime errors.


100-100: Schema retrieval
Similar single-model schema fetch ensures consistent logic across the codebase.


105-107: Mapping versioned items
Using lo.Map again to build GraphQL items from versioned data. Seamless and clear.


131-131: Item conversion in Search
itm := gqlmodel.ToItem(i, sp) aligns with the single package approach. Good consistency with the rest of the file.


18-18:

❓ Verification inconclusive

Imported trace from opencensus
Adding distributed tracing is beneficial for monitoring. Make sure spans are properly ended in all error paths, so resources aren’t leaked.

Would you like me to scan the repo for any unended spans or partial usage of trace to confirm correctness?


🏁 Script executed:

#!/bin/bash
ast-grep --pattern $'trace.StartSpan($_, $_)' 

Length of output: 257


Verify Proper Ending of Tracing Spans

The AST grep confirmed that distributed tracing is initiated via trace.StartSpan in both the GraphQL loader (server/internal/adapter/gql/loader_item.go:111) and the Mongo search (server/internal/infrastructure/mongo/item_search.go:25). Please ensure that for every span started in these locations, the corresponding span.End() is called on all execution paths—including error/exception cases—to prevent resource leaks.

server/pkg/item/item.go (2)

21-28: Reordered and introduced fields in Item struct
The new or updated fields (fields Fields, integration *IntegrationID, isMetadata) are consistent with the revised architecture. Ensure null pointer usage is safe, especially for optional integration references.


121-121: Delegating field lookups to i.fields.Field()
This direct delegation is clean and avoids redundant loops. No issues noted.

server/e2e/integration_item_test.go (8)

88-88: Use of fixed key "text" instead of random
Replacing id.RandomKey() with id.NewKey("text") helps produce stable results and simplifie test expectations.


1528-1539: Added asset field with nil value in test
These lines introduce an additional map for “asset” references set to nil. This tests default or empty states for asset fields. Good thoroughness in coverage.


1568-1580: Metadata field addition in create item tests
Here you’re adding “metadataFields” referencing a boolean field. This ensures coverage of sets that mix normal and metadata fields. Tests appear correct and well-structured.


1730-1735: Update item’s asset field
Switching the item’s second field to reference an existing asset ID. This confirms correct patch behavior and referencing.


1833-1838: Restoring group field
Ensuring that the group field for fId6 references multiple group IDs. This validates the item’s ability to handle multiple references in arrays.


1881-1886: Extending group references
Adding a third group reference tests “multiple” group fields. This thorough coverage is beneficial for verifying the system’s expansions.


2070-2074: Group field in retrieved item
On retrieval, verifying we get the correct group field ID, type, and values array. All changes align with group item expansions.


2153-2181: Assert item reflection

  1. Checking parents is empty and refs is ["latest"] confirms correct references for newly created items.
  2. Asserting exactly two fields: one text, one asset.
  3. Conditional check for embedded asset object vs. plain asset ID clarifies coverage of both embedded and non-embedded asset responses.

All changes are consistent with the broader refactor.

server/pkg/integrationapi/value.go (1)

93-99: Check for potential nil values when calling v.First().

Here, if v is empty, v.First() returns nil. Calling NewValue(nil, sf, cc) can result in a panic unless you handle a nil argument inside NewValue.

server/internal/adapter/gql/gqlmodel/convert_item.go (4)

12-12: New function signature looks good.

Accepting a schema.Package instead of separate schema parameters simplifies handling of group vs. main schema. This is consistent with the unified approach across the codebase.


31-31: No direct issues with assigning toItemFields.

However, verify that toItemFields correctly handles all field scenarios, including group fields. The logic looks sound but consider adding tests for edge cases (e.g., empty schema.Package).


37-37: New helper function approach is clear.

toItemFields consolidates the logic for normalizing fields in one place. This is a clean design choice.


39-40: Ensure sp.Field(f.FieldID()) is valid.

If sp.Field(f.FieldID()) returns nil, calling .Multiple() on it can lead to a panic. Confirm that NormalizedFields references only valid field IDs in the schema.

server/pkg/integrationapi/asset.go (7)

8-8: Parameter rename to embed is clearer.

Renaming from a more ambiguous all to embed clarifies the intent of controlling recursive embedding. This improves readability.


26-31: Synchronize preview and file creation logic.

These lines correctly invoke NewPreviewType, NewAssetFile, and NewAssetArchiveExtractionStatus. Just ensure errors in subcalls (e.g., a missing file) won't produce partially populated assets.


35-35: Straightforward approach for archive status mapping.

NewAssetArchiveExtractionStatus returns nil on unknown status, which is consistent with the existing pattern.


42-48: Enum mappings confirmed.

The switch covers known statuses (Done, Failed, InProgress, Pending) and defaults to nil. This is a clear fallback mechanism.


55-55: Good separation of concerns in NewAssetFile.

The function is well-defined for building file metadata. Passing embed keeps the logic consistent with NewAsset.


61-63: Watch for potential infinite recursion in nested files.

If a parent asset file references itself as a child, recursively calling NewAssetFile(c, true) might lead to an infinite loop. Confirm that cyclical references are disallowed or handled.


83-83: Simple rename to NewPreviewType is correct.

The function maintains the previous mappings while clarifying naming consistency.

server/pkg/integrationapi/item.go (2)

43-71: Prevent potential duplication or cyclic expansions in newReferencedItems.

This method builds additional referenced items by scanning fields for value.TypeReference. Verify that cyclical references, referenced item duplicates, or deep dependency trees won't cause performance or recursion issues.


73-98: Ensure schema field lookups are always valid.

NewFields calls sf := sp.Field(f.FieldID()); if the schema package lacks that field, subsequent operations like sf.Key() can panic. Double-check that i.NormalizedFields(sp) doesn’t produce invalid field IDs.

server/pkg/integrationapi/convert_context.go (5)

16-17: Unused afEmbed field.
The afEmbed field is declared but never utilized. If it's intended for embedding files, please implement the logic; otherwise, remove to avoid confusion.


54-66: Efficient asset loading.
The use of lo.Uniq(lo.FlatMap(...)) to gather and deduplicate asset IDs is a neat approach. Ensure that potential errors from c.loaders.Asset are handled properly, but overall this looks good.


90-102: Meta items loading strategy.
This logic parallels the reference loading. It seems well-structured and consistent with the rest of the constructor flow.


128-133: Meta item resolution is straightforward.
This method is direct and consistent with other resolution functions. It properly handles a nil context and empty list.


135-140: Referenced item resolution is straightforward.
The function closely mirrors ResolveMetaItem. The design is coherent and maintains consistency.

server/internal/adapter/integration/item.go (11)

8-8: Import addition.
No concerns here: importing "github.com/reearth/reearth-cms/server/internal/usecase" is consistent with existing usage.


14-14: Model package import.
The addition of "github.com/reearth/reearth-cms/server/pkg/model" is valid for referencing the model.Model type.


39-40: Embedding assets integration.
Invoking shouldEmbedAsset and using both return values is correct, but note that afEmbed might not be leveraged in the ConvertContext. Verify the intended usage.


46-46: Refactored call to NewVersionedItem.
Passing the new ConvertContext to NewVersionedItem aligns properly with the updated signature.


137-137: Query updated to find items by schema.
Switching to FindBySchema is consistent with the rest of the refactor. Ensure that any explicit query filters are no longer needed or are handled elsewhere.


360-361: Embedding assets for item update.
Using shouldEmbedAsset is consistent. The second bool might remain unused in the current code.


366-366: Return of the updated item with embedding.
Passing cc to create the updated versioned item is correct.


408-408: Returning item with new context.
Consistent usage of NewVersionedItem for a single item fetch response.


446-449: Explicit asset embedding flags.
NewCC(item.VersionedList{i}, true, false, loaders(ctx)) sets true for aEmbed and false for afEmbed; verify that ignoring file embedding is intentional.


451-451: Pointer conversion for consistent return.
Uses lo.ToPtr(integrationapi.NewVersionedItem(...)), aligning with other item creation flows.


462-470: Loader functions.
These lambdas provide a clean integration layer. The pattern for retrieving assets and items by IDs is straightforward, with separate functions for each.

Comment on lines +243 to 250
sp, err := usecases(ctx).Schema.FindByModel(ctx, itm[0].Value().Model(), op)
if err != nil {
return nil, err
}

return &gqlmodel.PublishItemPayload{
Items: lo.Map(itm, func(t item.Versioned, _ int) *gqlmodel.Item { return gqlmodel.ToItem(t, s, nil) }),
Items: lo.Map(itm, func(t item.Versioned, _ int) *gqlmodel.Item { return gqlmodel.ToItem(t, sp) }),
}, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Schema retrieval and array safety verification needed.

The code now uses the model ID from the first item in the result array.

While this approach is more efficient for retrieving schemas, there's a potential issue if the itm array is empty. Consider adding a check to handle this case.


🏁 Script executed:

#!/bin/bash
# Description: Check for error handling when item array might be empty

# Search for other places where the first element of an array is accessed without a check
rg -A 5 -B 5 '\[[0-9]\]' --include "*.go" | grep -v "test"

Length of output: 500


Schema Retrieval and Array Safety Check Required

The current implementation retrieves the schema using the model ID from the first item in the itm slice, optimizing the retrieval process. However, if itm is empty, directly accessing itm[0] can result in a runtime error. Please add a guard clause to verify that itm contains at least one element before proceeding. For example:

if len(itm) == 0 {
    return nil, errors.New("no items found")
}
sp, err := usecases(ctx).Schema.FindByModel(ctx, itm[0].Value().Model(), op)
if err != nil {
    return nil, err
}

return &gqlmodel.PublishItemPayload{
    Items: lo.Map(itm, func(t item.Versioned, _ int) *gqlmodel.Item { return gqlmodel.ToItem(t, sp) }),
}, nil

Affected Location

  • File: server/internal/adapter/gql/resolver_item.go, Lines: 243-250

Comment on lines +264 to 270
sp, err := usecases(ctx).Schema.FindByModel(ctx, res[0].Value().Model(), op)
if err != nil {
return nil, err
}
return &gqlmodel.UnpublishItemPayload{
Items: lo.Map(res, func(t item.Versioned, _ int) *gqlmodel.Item { return gqlmodel.ToItem(t, s, nil) }),
Items: lo.Map(res, func(t item.Versioned, _ int) *gqlmodel.Item { return gqlmodel.ToItem(t, sp) }),
}, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Schema retrieval and array safety verification needed.

Similar to the PublishItem resolver, this code accesses the first element of the res array without checking if it's empty.

Consider adding a check to ensure the array isn't empty before accessing its elements.


🏁 Script executed:

#!/bin/bash
# Description: Check error handling in unpublish case

# Search for how errors are handled in similar array-returning functions
rg -A 10 'Unpublish\(' --include "*.go" | grep -v "test"

Length of output: 498


Ensure Array Safety for res[0] in Unpublish Resolver

In server/internal/adapter/gql/resolver_item.go (lines 264-270), the code directly accesses res[0] without confirming that the slice is non-empty. Similar to the check present in the PublishItem resolver, please add a guard (e.g., verifying that len(res) > 0) before accessing the first element. This will prevent potential index-out-of-bound errors when res is empty.

Comment on lines +108 to +126
func (c *ConvertContext) ResolveAsset(id asset.ID) *Asset {
if c == nil || c.aMap == nil {
return nil
}

a, ok := c.aMap[id]
if !ok {
return nil
}

url := ""
if c.aBaseURL != nil {
url = c.aBaseURL(a)
}

f := c.aFiles[id]

return NewAsset(a, f, url, c.aEmbed)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Potential mismatch with afEmbed.
ResolveAsset constructs the asset but exclusively checks c.aEmbed. If there's a reason to distinguish file embedding separately (afEmbed), it should be passed here. Otherwise, consider removing afEmbed.

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.

1 participant