@adobe/data 0.9.72 → 0.9.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/references/data-lit/package.json +1 -1
- package/references/data-lit/src/elements/database-element.ts +24 -31
- package/references/data-lit/src/elements/database-element.type-test.ts +8 -0
- package/references/data-lit-tictactoe/package.json +1 -1
- package/references/data-react/package.json +1 -1
- package/references/data-react-hello/package.json +1 -1
- package/references/data-react-pixie/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
|
|
3
3
|
import { LitElement } from 'lit';
|
|
4
|
-
import { property } from 'lit/decorators.js';
|
|
5
4
|
import { iterateSelfAndAncestors } from '../functions/index.js';
|
|
6
5
|
import { Database } from '@adobe/data/ecs';
|
|
7
6
|
import { UIService } from '@adobe/data/service';
|
|
@@ -9,32 +8,23 @@ import { attachDecorator, withHooks } from '../index.js';
|
|
|
9
8
|
|
|
10
9
|
export abstract class DatabaseElement<P extends Database.Plugin> extends LitElement {
|
|
11
10
|
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
* created from `plugin` on connect. Bootstrap containers (those that own a
|
|
15
|
-
* controller or drive a streaming async-generator transaction) and ancestor
|
|
16
|
-
* injection use this; ordinary consumers inject and read through `service`
|
|
17
|
-
* instead.
|
|
18
|
-
*
|
|
19
|
-
* Deliberately documented in prose rather than with the internal JSDoc tag:
|
|
20
|
-
* this package emits with `stripInternal`, so that tag would erase this
|
|
21
|
-
* declaration from the public `.d.ts`. It must survive because
|
|
22
|
-
* `findAncestorDatabase` duck-types `element.database` across instances and
|
|
23
|
-
* bootstrap subclasses read it directly.
|
|
24
|
-
*/
|
|
25
|
-
@property({ type: Object, reflect: false })
|
|
26
|
-
database!: Database.Plugin.ToDatabase<P>;
|
|
11
|
+
/** Full database, hard-private — invisible to subclasses and external callers. */
|
|
12
|
+
#database!: Database.Plugin.ToDatabase<P>;
|
|
27
13
|
|
|
28
14
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* every mutator
|
|
15
|
+
* The element's database surface.
|
|
16
|
+
* - SET to inject the full database (DI).
|
|
17
|
+
* - GET returns the UI-restricted view (every mutator rewritten to
|
|
18
|
+
* fire-and-forget `void`).
|
|
19
|
+
* Divergent get/set types are intentional: inject full, consume restricted.
|
|
32
20
|
*/
|
|
33
|
-
get service(): UIService.FromService<Database.Plugin.ToDatabase<P>> {
|
|
34
|
-
return UIService.restrict(this.database);
|
|
35
|
-
}
|
|
36
21
|
set service(db: Database.Plugin.ToDatabase<P>) {
|
|
37
|
-
|
|
22
|
+
const old = this.#database;
|
|
23
|
+
this.#database = db;
|
|
24
|
+
this.requestUpdate('service', old);
|
|
25
|
+
}
|
|
26
|
+
get service(): UIService.FromService<Database.Plugin.ToDatabase<P>> {
|
|
27
|
+
return UIService.restrict(this.#database);
|
|
38
28
|
}
|
|
39
29
|
|
|
40
30
|
constructor() {
|
|
@@ -45,19 +35,22 @@ export abstract class DatabaseElement<P extends Database.Plugin> extends LitElem
|
|
|
45
35
|
abstract get plugin(): P;
|
|
46
36
|
|
|
47
37
|
connectedCallback(): void {
|
|
48
|
-
if (!this
|
|
49
|
-
const ancestor = this.
|
|
50
|
-
this.
|
|
38
|
+
if (!this.#database) {
|
|
39
|
+
const ancestor = this.findAncestorService();
|
|
40
|
+
this.service = ancestor?.extend(this.plugin) ?? Database.create(this.plugin);
|
|
51
41
|
}
|
|
52
42
|
super.connectedCallback();
|
|
53
43
|
}
|
|
54
44
|
|
|
55
|
-
protected
|
|
45
|
+
protected findAncestorService(): Database | void {
|
|
56
46
|
for (const element of iterateSelfAndAncestors(this)) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
47
|
+
// Read each ancestor's `service`. A DatabaseElement returns its full
|
|
48
|
+
// database here (UIService.restrict is identity at runtime); a foreign
|
|
49
|
+
// host (`<div .service=${db}>`) returns whatever was bound. Database.is
|
|
50
|
+
// keeps only a real database, skipping unconnected elements (undefined)
|
|
51
|
+
// and unrelated services (e.g. an ApplicationElement's MainService).
|
|
52
|
+
const { service } = element as { service?: unknown };
|
|
53
|
+
if (Database.is(service)) return service;
|
|
61
54
|
}
|
|
62
55
|
}
|
|
63
56
|
|
|
@@ -50,6 +50,14 @@ const _rejectRestrictedAssignment = (el: _CountElement): void => {
|
|
|
50
50
|
el.service = el.service;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
// 0a. The full database is fully encapsulated: there is no `database` member of
|
|
54
|
+
// any visibility on the instance type. `service` is the only surface.
|
|
55
|
+
const _noPublicDatabaseProperty = (el: _CountElement): void => {
|
|
56
|
+
// @ts-expect-error `database` no longer exists; the full db is hard-private
|
|
57
|
+
void el.database;
|
|
58
|
+
};
|
|
59
|
+
type _CheckNoDatabaseKey = Assert<Equal<Extract<keyof _CountElement, "database">, never>>;
|
|
60
|
+
|
|
53
61
|
// 1. The exposed service type is the UIService-restricted view of the database.
|
|
54
62
|
type _CheckRestricted = Assert<Equal<ServiceType, UIService.FromService<RawDatabase>>>;
|
|
55
63
|
|