Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-monorepo",
"version": "0.9.78",
"version": "0.9.79",
"private": true,
"scripts": {
"build": "pnpm -r run build",
Expand Down
2 changes: 1 addition & 1 deletion packages/data-ai/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-ai",
"version": "0.9.78",
"version": "0.9.79",
"description": "Cross-agent architecture skills for @adobe/data — installable as a Claude Code plugin or copied into any Agent-Skills-compatible agent (Cursor, Codex).",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-gpu-samples/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-gpu-samples",
"version": "0.9.78",
"version": "0.9.79",
"description": "WebGPU samples built on @adobe/data-gpu",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-gpu/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-gpu",
"version": "0.9.78",
"version": "0.9.79",
"description": "Adobe data WebGPU plugins and types for graphics and compute",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit-tictactoe/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-lit-tictactoe",
"version": "0.9.78",
"version": "0.9.79",
"description": "Tic-Tac-Toe sample - Lit web components with @adobe/data-lit and AgenticService",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit-todo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-lit-todo",
"version": "0.9.78",
"version": "0.9.79",
"description": "Todo sample app demonstrating @adobe/data with Lit",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-lit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-lit",
"version": "0.9.78",
"version": "0.9.79",
"description": "Adobe data Lit bindings - hooks, elements, decorators",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-p2p-tictactoe/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-p2p-tictactoe",
"version": "0.9.78",
"version": "0.9.79",
"description": "Serverless P2P tic-tac-toe — WebRTC DataChannel + @adobe/data-sync",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-persistence/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-persistence",
"version": "0.9.78",
"version": "0.9.79",
"description": "Worker-based incremental persistence layer for @adobe/data ECS over OPFS (browser) and node:fs (server).",
"type": "module",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-react-hello/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-react-hello",
"version": "0.9.78",
"version": "0.9.79",
"description": "Hello World sample - click counter using @adobe/data-react",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-react-pixie/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-react-pixie",
"version": "0.9.78",
"version": "0.9.79",
"description": "PixiJS React sample - ECS sprites (bunny, fox) with @adobe/data-react",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-react",
"version": "0.9.78",
"version": "0.9.79",
"description": "Adobe data React bindings — hooks and context for ECS database",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-solid-dashboard/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "data-solid-dashboard",
"version": "0.9.78",
"version": "0.9.79",
"description": "Mini dashboard sample — multiple components sharing one @adobe/data ECS database with SolidJS",
"type": "module",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-solid/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-solid",
"version": "0.9.78",
"version": "0.9.79",
"description": "Adobe data SolidJS bindings — context and provider for ECS database",
"type": "module",
"private": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data-sync/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data-sync",
"version": "0.9.78",
"version": "0.9.79",
"description": "Multi-user real-time synchronisation for @adobe/data ECS — server, client, and in-process loopback.",
"type": "module",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/data/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adobe/data",
"version": "0.9.78",
"version": "0.9.79",
"description": "Adobe data oriented programming library",
"type": "module",
"sideEffects": false,
Expand Down
119 changes: 119 additions & 0 deletions packages/data/src/ecs/database/observe-select-entities.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,125 @@ describe("observeSelectEntities", () => {
unsubscribe();
});

it("should notify when a required component is removed, dropping the entity from the result set", async () => {
const observer = vi.fn();
// Select on position+health but NOT filtered/ordered on either. This is the
// membership-contraction case: removing `health` migrates the row to the
// position-only archetype, so it leaves the result set even though the
// caller never filters or orders on health.
const unsubscribe = database.observe.select(["position", "health"])(observer);

expect(observer).toHaveBeenCalledTimes(1);
expect(observer.mock.calls[0][0]).toContain(entities.posHealth1);

// Remove the `health` component (undefined => column removal) so the entity
// migrates out of the position+health archetype.
database.transactions.updateEntity({
entity: entities.posHealth1,
values: { health: undefined }
});

await Promise.resolve();

// Must re-emit without the entity that left the result set.
expect(observer).toHaveBeenCalledTimes(2);
expect(observer.mock.calls[1][0]).not.toContain(entities.posHealth1);

unsubscribe();
});

it("should NOT notify when removing a component the query does not select", async () => {
const observer = vi.fn();
// Selecting only position: removing `health` from a position+health entity
// keeps it a member (its archetype is still a superset of {position}), so
// no re-emit should occur — the O(changes) early-exit must still fire.
const unsubscribe = database.observe.select(["position"])(observer);

expect(observer).toHaveBeenCalledTimes(1);
expect(observer.mock.calls[0][0]).toContain(entities.posHealth1);

database.transactions.updateEntity({
entity: entities.posHealth1,
values: { health: undefined }
});

await Promise.resolve();

// Still a member => no new notification.
expect(observer).toHaveBeenCalledTimes(1);

unsubscribe();
});

it("should drop an entity that gains an excluded component", async () => {
const observer = vi.fn();
// Select position, excluding health. posName entities qualify; adding health
// to one must remove it from the result set even though `health` is neither
// an include nor a where/order key.
const unsubscribe = database.observe.select(["position"], { exclude: ["health"] })(observer);

expect(observer).toHaveBeenCalledTimes(1);
expect(observer.mock.calls[0][0]).toContain(entities.posName1);
expect(observer.mock.calls[0][0]).not.toContain(entities.posHealth1);

database.transactions.updateEntity({
entity: entities.posName1,
values: { health: 50 }
});

await Promise.resolve();

expect(observer).toHaveBeenCalledTimes(2);
expect(observer.mock.calls[1][0]).not.toContain(entities.posName1);

unsubscribe();
});

it("should add an entity that loses an excluded component", async () => {
const observer = vi.fn();
const unsubscribe = database.observe.select(["position"], { exclude: ["health"] })(observer);

expect(observer).toHaveBeenCalledTimes(1);
expect(observer.mock.calls[0][0]).not.toContain(entities.posHealth1);

// Remove health => posHealth1 becomes a position-only entity, now qualifying.
database.transactions.updateEntity({
entity: entities.posHealth1,
values: { health: undefined }
});

await Promise.resolve();

expect(observer).toHaveBeenCalledTimes(2);
expect(observer.mock.calls[1][0]).toContain(entities.posHealth1);

unsubscribe();
});

it("should add an entity that migrates into a not-yet-seen archetype", async () => {
const observer = vi.fn();
// Select position+score. Initially only Full entities qualify. Give a
// position-only entity a score, migrating it into a brand-new archetype
// (position+score) that did not exist when the subscription was created —
// the memoized classifier must recognise it on first sight.
const unsubscribe = database.observe.select(["position", "score"])(observer);

expect(observer).toHaveBeenCalledTimes(1);
expect(observer.mock.calls[0][0]).not.toContain(entities.pos1);

database.transactions.updateEntity({
entity: entities.pos1,
values: { score: 42 }
});

await Promise.resolve();

expect(observer).toHaveBeenCalledTimes(2);
expect(observer.mock.calls[1][0]).toContain(entities.pos1);

unsubscribe();
});

it("should handle entity updates", async () => {
const observer = vi.fn();
const unsubscribe = database.observe.select(["position", "health"])(observer);
Expand Down
Loading