Skip to content

feat: Implement 'internalId' via Collection Identity Hook #9070

@tobiu

Description

@tobiu

Context:
Currently, Neo.mjs relies on the record's primary key (keyProperty) for DOM element IDs (e.g., view__1). This presents several challenges:

  1. Phantom Records: New records have no ID (null), causing DOM ID collisions (view__null).
  2. DOM Security: Exposing database IDs in the DOM allows for enumeration attacks.
  3. Stability: Saving a record changes its ID (e.g., -1 -> 100), forcing a destructive DOM update.
  4. Cross-Store Uniqueness: Drag-and-drop between stores can lead to ID collisions if different entities share the same PK.

Objective:
Implement a stable, globally unique internalId (e.g., neo-record-1) for all data items (Records and Raw Objects), maintained via a lightweight Symbol property.

Architecture: The "Identity Provider" Pattern
To maintain the separation of concerns between Neo.collection.Base (dumb container) and Neo.data.Store (smart data manager), we will introduce an itemFactory hook.

Implementation Plan:

  1. Define Symbol:

    • Create src/util/Symbol.mjs (or similar) to export const internalId = Symbol.for('neoInternalId');.
  2. Enhance Neo.collection.Base:

    • Add itemFactory config (Function).
    • Inside the splice method's addition loop, invoke the hook:
      me.itemFactory?.(item);
    • Documentation: Add intent-driven JSDoc explaining this is an injection point for item augmentation (like identity) without requiring inheritance.
  3. Update Neo.data.Store:

    • Implement assignInternalId(item) method.
    • In construct, bind this method to the itemFactory config.
    • Logic:
      if (!item[internalId]) {
          item[internalId] = Neo.getId('record');
      }
  4. Update Neo.data.RecordFactory:

    • Ensure created Records also receive this symbol during instantiation.
  5. Expose Accessor:

    • Add store.getInternalId(item) helper.

Outcome:

  • Zero Iteration Overhead: Piggybacks on the existing Collection map generation loop.
  • Decoupled: Collection remains ignorant of "Records".
  • Secure & Stable: Provides the foundation for immutable DOM identities.

Metadata

Metadata

Assignees

Labels

coreCore framework functionalityenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions