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.65",
"version": "0.9.66",
"private": true,
"scripts": {
"build": "pnpm -r run build",
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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"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.65",
"version": "0.9.66",
"description": "Adobe data oriented programming library",
"type": "module",
"sideEffects": false,
Expand Down
19 changes: 15 additions & 4 deletions packages/data/src/ecs/database/create-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,26 @@ function validatePropertyOrder(plugins: Record<string, unknown>): void {
*/
type FullDBForPlugin<
CS, RS, A, TD, S extends string, AD, XP extends Database.Plugin,
SVF extends ServiceFactories<Database.FromPlugin<XP>>
SVF extends ServiceFactories<Database.FromPlugin<XP>>,
IX = {}
> = Database<
FromSchemas<CS & XP['components']>,
FromSchemas<RS & XP['resources']>,
A & XP['archetypes'],
ToTransactionFunctions<TD & XP['transactions']>,
S | StringKeyof<XP['systems']>,
ToActionFunctions<AD & XP['actions']>,
FromServiceFactories<RemoveIndex<SVF> & XP['services']>
FromServiceFactories<RemoveIndex<SVF> & XP['services']>,
// 8: CV — placeholder. Kept `unknown` (Database's own default for this slot)
// so a concrete computed-values type never constrains computed-factory
// inference / breaks contravariance. Must be supplied explicitly because
// slot 9 (IX) sits after it.
unknown,
// 9: IX — thread the index declarations so `db.indexes` is populated inside
// computed factories, same as the actions/systems `db` already does.
// XP is AmbientPlugin<XP, IP> at the call sites, so XP['indexes'] carries
// both extends-base and imports-dep indexes; `IX` adds the plugin's own.
IX & XP['indexes']
>;

/**
Expand Down Expand Up @@ -177,7 +188,7 @@ export function createPlugin<
const AD,
const S extends string = never,
const SVF extends ServiceFactories<Database.FromPlugin<AmbientPlugin<XP, IP>>> = {},
const CVF extends PluginComputedFactories<FullDBForPlugin<RemoveIndex<CS>, RemoveIndex<RS>, RemoveIndex<A>, RemoveIndex<TD>, S, RemoveIndex<AD> & XP['actions'] & IP['actions'], AmbientPlugin<XP, IP>, RemoveIndex<SVF>>> = {},
const CVF extends PluginComputedFactories<FullDBForPlugin<RemoveIndex<CS>, RemoveIndex<RS>, RemoveIndex<A>, RemoveIndex<TD>, S, RemoveIndex<AD> & XP['actions'] & IP['actions'], AmbientPlugin<XP, IP>, RemoveIndex<SVF>, RemoveIndex<IX>>> = {},
>(
plugins: {
imports?: IP,
Expand All @@ -189,7 +200,7 @@ export function createPlugin<
resources?: RS,
archetypes?: A,
indexes?: IX,
computed?: CVF & PluginComputedFactories<FullDBForPlugin<RemoveIndex<CS>, RemoveIndex<RS>, RemoveIndex<A>, {}, string, RemoveIndex<AD> & XP['actions'] & IP['actions'], AmbientPlugin<XP, IP>, RemoveIndex<SVF>>>,
computed?: CVF & PluginComputedFactories<FullDBForPlugin<RemoveIndex<CS>, RemoveIndex<RS>, RemoveIndex<A>, {}, string, RemoveIndex<AD> & XP['actions'] & IP['actions'], AmbientPlugin<XP, IP>, RemoveIndex<SVF>, RemoveIndex<IX>>>,
transactions?: TD,
actions?: AD & {
readonly [K: string]: (db: Database<
Expand Down
50 changes: 50 additions & 0 deletions packages/data/src/ecs/database/database.index.type-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,53 @@ function invalidUniqueGetWrongType() {
db.indexes.uniqueByEmail.get({ email: "x@y.z" });
};
}

// ============================================================================
// VALID — computed factories see db.indexes
//
// Regression guard: FullDBForPlugin used to forward only Database slots 1–7,
// so the IX slot (9) fell back to its `{}` default and `db.indexes` was empty
// inside computed factories. The declarations below would not compile if that
// regressed — `db.indexes.<name>` would be an error.
// ============================================================================

function computedSeesOwnIndexes() {
createPlugin({
components: {
email: { type: "string" },
name: { type: "string" },
},
indexes: {
byName: { key: "name" },
},
computed: {
probe: (db) => {
type Handle = typeof db.indexes.byName;
type _FindArg = Assert<Equal<Parameters<Handle["find"]>[0], { readonly name: string }>>;
return Observe.fromConstant(db.indexes.byName.find({ name: "x" }).length);
},
},
});
}

function computedSeesImportedAndExtendedIndexes() {
const base = createPlugin({
components: { email: { type: "string" } },
indexes: { uniqueByEmail: { key: "email", unique: true } },
});
const dep = createPlugin({
components: { name: { type: "string" } },
indexes: { byName: { key: "name" } },
});

createPlugin({
extends: base,
imports: dep,
computed: {
// Index from `extends` base...
fromExtends: (db) => Observe.fromConstant(db.indexes.uniqueByEmail.get({ email: "x@y.z" })),
// ...and index from `imports` dependency.
fromImports: (db) => Observe.fromConstant(db.indexes.byName.find({ name: "x" }).length),
},
});
}