@mosaicast/plugin-sdk 0.4.0 → 0.6.0
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/README.md +57 -7
- package/dist/index.d.ts +153 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -31,8 +31,8 @@ The contract version is a **single SemVer anchor** mirrored in four places that
|
|
|
31
31
|
(CI enforces it): `build.gradle.kts` · `package.json` · `PlatformApi.VERSION` · `PLATFORM_API_VERSION`.
|
|
32
32
|
|
|
33
33
|
**How the host matches it:** core compares `major.minor` **exactly**. A plugin declaring `0.3.x` is
|
|
34
|
-
rejected the moment the host runs `0.
|
|
35
|
-
is pre-1.0 a breaking change is therefore a **minor** bump (`0.
|
|
34
|
+
rejected the moment the host runs `0.6.0` — with the reason shown in the admin log viewer. While the SDK
|
|
35
|
+
is pre-1.0 a breaking change is therefore a **minor** bump (`0.5.0` → `0.6.0`), not a major one; from
|
|
36
36
|
`1.0.0` on, normal SemVer applies and breaking means major.
|
|
37
37
|
|
|
38
38
|
## Build & test
|
|
@@ -49,8 +49,8 @@ npm ci && npm run build # TypeScript: src → dist (.js + .d.ts)
|
|
|
49
49
|
- Released: from **GitHub Packages** (see below).
|
|
50
50
|
```kotlin
|
|
51
51
|
dependencies {
|
|
52
|
-
compileOnly("dev.mosaicast:plugin-api:0.
|
|
53
|
-
testImplementation("dev.mosaicast:plugin-testkit:0.
|
|
52
|
+
compileOnly("dev.mosaicast:plugin-api:0.6.0") // contract, provided by the host
|
|
53
|
+
testImplementation("dev.mosaicast:plugin-testkit:0.6.0") // test doubles only
|
|
54
54
|
}
|
|
55
55
|
```
|
|
56
56
|
Sources + Javadoc JARs give IDE hover docs automatically.
|
|
@@ -99,16 +99,66 @@ DELETE /api/plugins/{id}/data/{scopeType}/{scopeId}/{key}
|
|
|
99
99
|
| upsert | `store().put(scope, key, value)` | `ctx.api.put('data/…/{key}', value)` |
|
|
100
100
|
| remove | `store().delete(scope, key)` → `boolean` | `ctx.api.delete('data/…/{key}')` |
|
|
101
101
|
|
|
102
|
-
- `scopeType` is `site | feed | season | episode` and `scopeId` is that entity's id — mirroring `Scope`/`ScopeType`, the same addressing the backend uses.
|
|
103
|
-
- `key` must match `DocStore.KEY_PATTERN` = `^[A-Za-z0-9._:-]{1,200}$` and is the final path segment, verbatim — no `/`, and no percent-encoded slash either (servlet containers reject `%2F` there). Structure keys with `:` / `.` / `-` instead, e.g. `mark:
|
|
102
|
+
- `scopeType` is `site | feed | season | episode | user` and `scopeId` is that entity's id — mirroring `Scope`/`ScopeType`, the same addressing the backend uses. Two are **singletons** whose id the SDK and the host both pin: `site`'s is always `main` (`Scope.SITE_ID`, one site) and `user`'s always `me` (`Scope.SELF_ID`, the calling user). So `Scope.site()` and `…/data/site/main/{key}` address the same document, and the path always has four non-empty segments.
|
|
103
|
+
- `key` must match `DocStore.KEY_PATTERN` = `^[A-Za-z0-9._:-]{1,200}$` and is the final path segment, verbatim — no `/`, and no percent-encoded slash either (servlet containers reject `%2F` there). Structure keys with `:` / `.` / `-` instead, e.g. `mark:s2e04:b3` (entity ids are slugs, not UUIDs). The host answers 400 on a bad key, and `InMemoryDocStore` throws `IllegalArgumentException` — so it fails in your tests, not in production.
|
|
104
104
|
- The list is **paginated** (core's standard `PagedResponse` envelope) and **carries keys** (`DocEntry`), because neither end can address a doc without one.
|
|
105
105
|
- `delete` is **idempotent**: removing an absent doc is not an error. The Java call returns whether anything was actually removed.
|
|
106
106
|
|
|
107
|
+
### Per-user data — the `user` scope (since 0.5.0)
|
|
108
|
+
|
|
109
|
+
**Per-user data belongs in the `user` scope, never in the key.** A key is client-supplied, so the convention this README used to suggest — `mark:<userId>:cell` under an episode scope — was an access-control decision the host could not enforce: any caller past the plugin's read floor could address someone else's key directly, and scope ids are public slugs, so nothing had to be guessed.
|
|
110
|
+
|
|
111
|
+
`Scope.user()` / `…/data/user/me/{key}` fixes that by construction:
|
|
112
|
+
|
|
113
|
+
- The id is always the sentinel `me` (`Scope.SELF_ID`), resolved **server-side from the session**. The canonical `Scope` constructor normalizes any `USER` id to it, so there is no expression in the Java API that names another person's partition — and there is deliberately **no `Scope.user(String)` overload**.
|
|
114
|
+
- Naming any other `user` id over HTTP is a **400**, never a silent substitution. An anonymous `user` request is a **401** whatever the read floor says: no session, no partition.
|
|
115
|
+
- The partition is **flat** — one per user, not one per user and entity — so the entity goes in the key: `mark:<episodeSlug>:cell`.
|
|
116
|
+
- `readableBy` does not apply to it. No floor makes someone else's partition readable.
|
|
117
|
+
|
|
118
|
+
**A backend has no calling user**, so every `DocStore` method throws `UnsupportedOperationException` for a `USER` scope — reads included, since resolving "me" without a caller would have to pick someone. Aggregate instead:
|
|
119
|
+
|
|
120
|
+
```java
|
|
121
|
+
// Backend-only, read-only, and no HTTP surface: no visitor's request can reach another's data.
|
|
122
|
+
List<OwnedDocEntry> marks = ctx.store().queryAcrossUsers("mark:");
|
|
123
|
+
// record OwnedDocEntry(UUID userId, String key, JsonNode value) — the owner is host-resolved, never
|
|
124
|
+
// a value the browser supplied, which is what makes a leaderboard built from it true.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Write the aggregate back to an entity scope (`…/data/episode/s2e04/leaderboard`) and let the component read it there. In tests, `InMemoryDocStore.asUser(uuid)` stands in for the host resolving `me`, so you can seed what a frontend would have written and then assert on `queryAcrossUsers`.
|
|
128
|
+
|
|
107
129
|
**The two ends see one store.** The doc a backend writes with `ctx.store().put(scope, key, value)` is exactly what the frontend reads at `GET /api/plugins/{id}/data/{scopeType}/{scopeId}/{key}`.
|
|
108
130
|
|
|
109
131
|
**What the host enforces**, so a plugin doesn't have to:
|
|
110
132
|
- Data is **hard-scoped to the plugin id** — a plugin can only ever see its own data.
|
|
111
|
-
- **
|
|
133
|
+
- **Access is what the manifest declares**, not what the slots imply: `"data": { "readableBy": "fan", "writableBy": "podcaster" }`. Values are `anonymous | fan | podcaster | admin`; `writableBy` may not be `anonymous`, and an absent block defaults `readableBy` to the **write** floor rather than to anonymous — saying nothing gets the safe answer. A slot's `visibleTo` governs **rendering only**; deriving the data floor from unrelated UI slots is what once let a plugin with one anonymous slot expose its whole store.
|
|
134
|
+
- **The floors say who, not which key** — see below.
|
|
135
|
+
- The host validates that the scope exists (and that the feed is enabled). `ctx.api` carries the user's auth (session or personal access token).
|
|
136
|
+
|
|
137
|
+
### Backend-owned keys (since 0.6.0) — a shared-scope document has no owner
|
|
138
|
+
|
|
139
|
+
Authorization on the data surface is **per plugin, not per document**. Every caller above your `writableBy` floor can overwrite or delete *any* key in a `site`/`feed`/`season`/`episode` scope — including a value your backend computed on a schedule, because the host cannot tell your write from a `curl`:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# podcaster, with a plugin declaring writableBy: "podcaster" — the floor did exactly what it says
|
|
143
|
+
curl -b cookie.podcaster -X PUT .../api/plugins/sample/data/site/main/stats \
|
|
144
|
+
-H "X-XSRF-TOKEN: $XT" -d '{"totalEpisodes":9999}' # 204, and every visitor now reads it
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
If your backend authors a key, **declare it**:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
"data": {
|
|
151
|
+
"readableBy": "anonymous",
|
|
152
|
+
"writableBy": "podcaster",
|
|
153
|
+
"backendOwned": ["stats", "agg:*"]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- Each entry is an exact key, a prefix ending in `*`, or the bare `*` (the whole store is computed) — `DocStore.BACKEND_OWNED_PATTERN` = `^(\*|[A-Za-z0-9._:-]{1,200}\*?)$`. A `*` in the middle, or an empty entry, is rejected at load. A pattern can never be a key, since `*` is not in `KEY_PATTERN`.
|
|
158
|
+
- A client `PUT`/`DELETE` to a matching key is **403**, worded differently from the role-floor 403 so you can tell which rule refused you. **Reads are untouched** and still governed by `readableBy`. `ctx.store()` — the backend — is unaffected, which is the whole point.
|
|
159
|
+
- **Write those keys in `register()` too, not only on a schedule.** The declaration refuses *new* client writes; it does not remove a value forged before it existed, so otherwise a bogus document survives until the next tick.
|
|
160
|
+
- It is **ignored for `user` scopes**: the backend cannot write a partition at all, so even a bare `*` leaves those to their owner.
|
|
161
|
+
- `PluginDataDeclaration` in the TS SDK types this block (documentation only — the host validates it), and `InMemoryDocStore.withBackendOwned(...)` enforces it in tests, so you can prove the forged `PUT` fails without a running host.
|
|
112
162
|
|
|
113
163
|
**No request-time server logic.** A write is plain persistence — no plugin code runs on the request. Anything derived, validated or aggregated server-side is **precomputed** in `register`/`onSchedule` and read back from the store.
|
|
114
164
|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,9 +17,18 @@
|
|
|
17
17
|
* rejects a mismatch at startup (ARCHITECTURE §7.2). While the SDK is pre-1.0 a breaking change is
|
|
18
18
|
* therefore a *minor* bump; from `1.0.0` on, breaking means major.
|
|
19
19
|
*/
|
|
20
|
-
export declare const PLATFORM_API_VERSION: '0.
|
|
20
|
+
export declare const PLATFORM_API_VERSION: '0.6.0';
|
|
21
21
|
/** A user's role (ARCHITECTURE §8.5). Anonymous visitors have no role (`user` is `null`). */
|
|
22
22
|
export type Role = 'admin' | 'podcaster' | 'fan';
|
|
23
|
+
/**
|
|
24
|
+
* A role as the manifest names it: the {@link Role} values plus `anonymous`, the absence of one.
|
|
25
|
+
*
|
|
26
|
+
* Used by the access floors in {@link PluginDataDeclaration}. `ctx.user` is `null` rather than
|
|
27
|
+
* `'anonymous'` — this spelling exists only where a manifest has to name "no role at all".
|
|
28
|
+
*
|
|
29
|
+
* @since 0.6.0
|
|
30
|
+
*/
|
|
31
|
+
export type DataAccessRole = Role | 'anonymous';
|
|
23
32
|
/**
|
|
24
33
|
* The severity of a {@link PluginContext.log} call.
|
|
25
34
|
*
|
|
@@ -35,13 +44,41 @@ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
|
35
44
|
* reference to a detached DOM tree and keeps firing into it.
|
|
36
45
|
*/
|
|
37
46
|
export type Unsubscribe = () => void;
|
|
38
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* The level plus concrete entity a view is scoped to (ARCHITECTURE §6.1).
|
|
49
|
+
*
|
|
50
|
+
* This is the **slot** scope — the page your component was mounted on. It never carries the `user` level
|
|
51
|
+
* of {@link DataScopeType}: a slot lives in a named region of a page, and there is no user page. A
|
|
52
|
+
* component reading per-user data addresses `data/user/me/…` explicitly while `ctx.scope` stays whatever
|
|
53
|
+
* page it is on.
|
|
54
|
+
*/
|
|
39
55
|
export interface Scope {
|
|
40
56
|
/** The scope level. */
|
|
41
57
|
type: 'site' | 'feed' | 'season' | 'episode';
|
|
42
|
-
/** The id of the entity at that level (e.g. the `EpisodeRef`
|
|
58
|
+
/** The id of the entity at that level (e.g. the `EpisodeRef` slug for `episode`). */
|
|
43
59
|
id: string;
|
|
44
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* The scope levels the host's **data** surface addresses — the four page levels of {@link Scope} plus
|
|
63
|
+
* `user`, the caller's own private partition (`ScopeType` in the Java SDK).
|
|
64
|
+
*
|
|
65
|
+
* Deliberately a second type: `user` is a storage partition, never a slot scope, so it can appear in a
|
|
66
|
+
* `data/{scopeType}/{scopeId}/…` path but never in `ctx.scope`.
|
|
67
|
+
*
|
|
68
|
+
* @since 0.5.0
|
|
69
|
+
*/
|
|
70
|
+
export type DataScopeType = Scope['type'] | 'user';
|
|
71
|
+
/**
|
|
72
|
+
* The id every `user` data path carries: the literal `me`, mirroring the Java `Scope.SELF_ID`.
|
|
73
|
+
*
|
|
74
|
+
* The host resolves it from the session, so `data/user/me/{key}` reaches the calling user's partition and
|
|
75
|
+
* no one else's. **Any other `user` id is a 400**, never a silent substitution, and an anonymous request
|
|
76
|
+
* to a `user` path is a 401 — with no session there is no partition. Per-user data belongs here rather
|
|
77
|
+
* than in a key like `mark:<userId>:cell`, which the host cannot enforce because the client supplies it.
|
|
78
|
+
*
|
|
79
|
+
* @since 0.5.0
|
|
80
|
+
*/
|
|
81
|
+
export declare const SELF_SCOPE_ID: 'me';
|
|
45
82
|
/**
|
|
46
83
|
* The host-owned filter axes for the current view (ARCHITECTURE §6.1).
|
|
47
84
|
*
|
|
@@ -135,38 +172,86 @@ export interface PagedDocs<T = unknown> {
|
|
|
135
172
|
* → remove; idempotent
|
|
136
173
|
* ```
|
|
137
174
|
*
|
|
138
|
-
* `scopeType` is
|
|
139
|
-
*
|
|
140
|
-
*
|
|
175
|
+
* `scopeType` is a {@link DataScopeType} and `scopeId` the id of that entity — i.e. the `Scope` the
|
|
176
|
+
* backend addresses with. Two of them are singletons whose id is fixed: `site` is always the literal
|
|
177
|
+
* `main` (one site), and `user` always {@link SELF_SCOPE_ID} (`me`), which the host resolves to the
|
|
178
|
+
* calling user. So the path always has four non-empty segments. `key` must match
|
|
141
179
|
* `^[A-Za-z0-9._:-]{1,200}$` — the host answers 400 otherwise — and is the final path segment verbatim:
|
|
142
|
-
* no `/`, so structure keys with `:` / `.` / `-` (e.g. `mark:
|
|
143
|
-
* ({@link PagedDocs}) and carries each doc's key ({@link DocEntry}), since you cannot
|
|
144
|
-
* without it.
|
|
180
|
+
* no `/`, so structure keys with `:` / `.` / `-` (e.g. `mark:s2e04:b3`; entity ids are slugs). The list
|
|
181
|
+
* is paginated ({@link PagedDocs}) and carries each doc's key ({@link DocEntry}), since you cannot
|
|
182
|
+
* address a doc without it.
|
|
145
183
|
*
|
|
146
184
|
* The doc a backend writes with `ctx.store().put(scope, key, value)` is the one read here at
|
|
147
|
-
* `GET /api/plugins/{id}/data/{scopeType}/{scopeId}/{key}`: one store, two ends.
|
|
185
|
+
* `GET /api/plugins/{id}/data/{scopeType}/{scopeId}/{key}`: one store, two ends. The `user` scope is the
|
|
186
|
+
* exception — it exists only here. A backend has no calling user, so it cannot write a user partition at
|
|
187
|
+
* all and reads them only in aggregate, through the Java `DocStore.queryAcrossUsers(prefix)`.
|
|
188
|
+
*
|
|
189
|
+
* ## Where per-user data goes
|
|
190
|
+
*
|
|
191
|
+
* **In the `user` scope, not in the key.** A key is client-supplied, so the older convention
|
|
192
|
+
* `mark:<userId>:cell` under an episode scope was an access-control decision the host could not check:
|
|
193
|
+
* any caller past the plugin's read floor could address someone else's key, and scope ids are public
|
|
194
|
+
* slugs, so nothing had to be guessed. `data/user/me/…` is resolved from the session instead — the only
|
|
195
|
+
* partition a caller can name is their own. Any other `user` id is a **400**; an anonymous `user` request
|
|
196
|
+
* is a **401**, whatever the read floor says. The partition is flat, so the entity goes in the key:
|
|
197
|
+
* `mark:<episodeSlug>:cell`.
|
|
198
|
+
*
|
|
199
|
+
* ## What the host enforces
|
|
200
|
+
*
|
|
201
|
+
* Data is hard-scoped to the plugin id — a plugin only ever sees its own — and the host validates that the
|
|
202
|
+
* scope exists. Access is what your **manifest** declares:
|
|
203
|
+
*
|
|
204
|
+
* ```json
|
|
205
|
+
* "data": {
|
|
206
|
+
* "readableBy": "fan",
|
|
207
|
+
* "writableBy": "podcaster",
|
|
208
|
+
* "backendOwned": ["stats", "agg:*"]
|
|
209
|
+
* }
|
|
210
|
+
* ```
|
|
148
211
|
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
212
|
+
* Values are `anonymous | fan | podcaster | admin` ({@link Role} plus `anonymous`, the absence of one);
|
|
213
|
+
* `writableBy` may not be `anonymous`, and if the block is absent `readableBy` falls back to the *write*
|
|
214
|
+
* floor rather than to anonymous — saying nothing gets the safe answer. A slot's `visibleTo` governs
|
|
215
|
+
* **rendering only**; it never governed data access, and inferring the data floor from unrelated UI slots
|
|
216
|
+
* is exactly what once let a plugin with one anonymous slot expose its whole store. Watch the default: a
|
|
217
|
+
* plugin with an anonymous slot and no `data` block loses its anonymous reads (403) until it declares
|
|
218
|
+
* `"readableBy": "anonymous"`. **Neither floor applies to the `user` scope:** no floor makes someone
|
|
219
|
+
* else's partition readable, none stands between a caller and their own, and `writableBy` does not gate it
|
|
220
|
+
* either — a write floor protects the *shared* surface, and a user partition is unshared. Any
|
|
221
|
+
* authenticated caller reads and writes their own `data/user/me/…` whatever the manifest declares.
|
|
222
|
+
*
|
|
223
|
+
* **The floors say who, not which key.** Authorization here is per plugin, not per document, so every
|
|
224
|
+
* caller above `writableBy` can overwrite or delete *any* shared-scope key — including one your backend
|
|
225
|
+
* computed, since the host cannot tell a scheduled write from a `curl`. `backendOwned` is the exception:
|
|
226
|
+
* an exact key or a `*`-terminated prefix that the backend still writes freely while a client `PUT` or
|
|
227
|
+
* `DELETE` answers **403**, worded differently from the role-floor 403 so you can tell which rule refused
|
|
228
|
+
* you. Reads are unaffected. It does not apply to `user` partitions, and it does not remove a value forged
|
|
229
|
+
* before it was declared — see {@link PluginDataDeclaration}.
|
|
230
|
+
*
|
|
231
|
+
* A write is plain persistence: no plugin code runs at request time, so anything derived or validated
|
|
232
|
+
* server-side must be precomputed in the backend's `register`/`onSchedule` and read back from the store.
|
|
154
233
|
*
|
|
155
234
|
* Custom plugin-defined server routes may arrive in a later `platformApi` version; v1 plugins use the
|
|
156
235
|
* doc store.
|
|
157
236
|
*
|
|
158
237
|
* @example Read, list, write and remove docs from a Web Component
|
|
159
238
|
* ```ts
|
|
160
|
-
* const
|
|
161
|
-
* const
|
|
239
|
+
* const mine = `data/user/${SELF_SCOPE_ID}`; // the caller's own partition
|
|
240
|
+
* const shared = `data/${ctx.scope.type}/${ctx.scope.id}`; // scope.id is `main` on the site scope
|
|
241
|
+
* const key = `mark:${ctx.scope.id}`; // no `/` in keys
|
|
162
242
|
*
|
|
163
|
-
* const
|
|
164
|
-
* await ctx.api.put(`${
|
|
243
|
+
* const marks = await ctx.api.get<Marks>(`${mine}/${key}`); // rejects with a 404 problem if absent
|
|
244
|
+
* await ctx.api.put(`${mine}/${key}`, { ...marks, b3: true }); // upsert, last-write-wins
|
|
165
245
|
*
|
|
166
|
-
* const page = await ctx.api.get<PagedDocs<
|
|
246
|
+
* const page = await ctx.api.get<PagedDocs<Marks>>(`${mine}?prefix=mark:&page=0&size=50`);
|
|
167
247
|
* page.items.forEach(({ key, value }) => render(key, value));
|
|
168
248
|
*
|
|
169
|
-
* await ctx.api.delete(`${
|
|
249
|
+
* await ctx.api.delete(`${mine}/${key}`); // idempotent
|
|
250
|
+
*
|
|
251
|
+
* // A leaderboard is not built here: the backend aggregates every user's marks with
|
|
252
|
+
* // queryAcrossUsers(...) and writes the result to `${shared}/leaderboard` for this component to read.
|
|
253
|
+
* // If the manifest declares that key backendOwned, a PUT to it from here is a 403 — by design.
|
|
254
|
+
* const board = await ctx.api.get<Leaderboard>(`${shared}/leaderboard`);
|
|
170
255
|
* ```
|
|
171
256
|
*/
|
|
172
257
|
export interface PluginApiClient {
|
|
@@ -346,6 +431,53 @@ export interface ConsentApi {
|
|
|
346
431
|
*/
|
|
347
432
|
onChange(cb: () => void): Unsubscribe;
|
|
348
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* The shape of your manifest's `data` block — who may reach the doc store over HTTP, and which keys only
|
|
436
|
+
* your backend may write.
|
|
437
|
+
*
|
|
438
|
+
* **This type is documentation, not enforcement**, on the same terms as {@link ConsentServiceDeclaration}:
|
|
439
|
+
* the manifest is owned and validated by the host, nothing here runs at load time, and if this type and
|
|
440
|
+
* core disagree, core wins. It is typed because the block carries a security control — a typo in
|
|
441
|
+
* `backendOwned` protects nothing and says nothing, which is the worst way for a declaration to fail.
|
|
442
|
+
*
|
|
443
|
+
* ```ts
|
|
444
|
+
* const data: PluginDataDeclaration = {
|
|
445
|
+
* readableBy: 'anonymous',
|
|
446
|
+
* writableBy: 'podcaster',
|
|
447
|
+
* backendOwned: ['stats', 'agg:*'],
|
|
448
|
+
* };
|
|
449
|
+
* ```
|
|
450
|
+
*
|
|
451
|
+
* @since 0.6.0
|
|
452
|
+
*/
|
|
453
|
+
export interface PluginDataDeclaration {
|
|
454
|
+
/**
|
|
455
|
+
* The minimum role that may **read** the doc store.
|
|
456
|
+
*
|
|
457
|
+
* Omit the whole block and this falls back to {@link writableBy}, not to `anonymous` — saying nothing
|
|
458
|
+
* gets the safe answer. Never applies to the `user` scope, which is the caller's own either way.
|
|
459
|
+
*/
|
|
460
|
+
readableBy?: DataAccessRole;
|
|
461
|
+
/**
|
|
462
|
+
* The minimum role that may **write** the doc store. May not be `anonymous`.
|
|
463
|
+
*
|
|
464
|
+
* Governs shared scopes only: a `user` partition is unshared, so its owner writes it whatever this says.
|
|
465
|
+
*/
|
|
466
|
+
writableBy: Exclude<DataAccessRole, 'anonymous'>;
|
|
467
|
+
/**
|
|
468
|
+
* Keys your backend authors, which clients may read but never `PUT` or `DELETE` (403).
|
|
469
|
+
*
|
|
470
|
+
* Each entry is an exact key, a prefix ending in `*`, or the bare `*` for "the whole store is computed"
|
|
471
|
+
* — matching `^(\*|[A-Za-z0-9._:-]{1,200}\*?)$`, mirrored from the Java `DocStore.BACKEND_OWNED_PATTERN`.
|
|
472
|
+
* A `*` in the middle, or an empty entry, is rejected when the plugin loads.
|
|
473
|
+
*
|
|
474
|
+
* Declare a key here **and write it in your backend's `register`**, not only on a schedule: the
|
|
475
|
+
* declaration refuses new client writes but does not remove a value a client wrote before it existed, so
|
|
476
|
+
* a forged document otherwise survives until the next tick. It is ignored for `user` partitions, which
|
|
477
|
+
* the backend cannot write at all — even a bare `*` leaves those to their owner.
|
|
478
|
+
*/
|
|
479
|
+
backendOwned?: string[];
|
|
480
|
+
}
|
|
349
481
|
/**
|
|
350
482
|
* One item a service stores on the visitor's device, as declared in `plugin.json`.
|
|
351
483
|
*
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,EAAG,OAAgB,CAAC;AAErD,6FAA6F;AAC7F,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,WAAW,GAAG,KAAK,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,18 @@
|
|
|
19
19
|
* rejects a mismatch at startup (ARCHITECTURE §7.2). While the SDK is pre-1.0 a breaking change is
|
|
20
20
|
* therefore a *minor* bump; from `1.0.0` on, breaking means major.
|
|
21
21
|
*/
|
|
22
|
-
export const PLATFORM_API_VERSION = '0.
|
|
22
|
+
export const PLATFORM_API_VERSION = '0.6.0';
|
|
23
|
+
/**
|
|
24
|
+
* The id every `user` data path carries: the literal `me`, mirroring the Java `Scope.SELF_ID`.
|
|
25
|
+
*
|
|
26
|
+
* The host resolves it from the session, so `data/user/me/{key}` reaches the calling user's partition and
|
|
27
|
+
* no one else's. **Any other `user` id is a 400**, never a silent substitution, and an anonymous request
|
|
28
|
+
* to a `user` path is a 401 — with no session there is no partition. Per-user data belongs here rather
|
|
29
|
+
* than in a key like `mark:<userId>:cell`, which the host cannot enforce because the client supplies it.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.5.0
|
|
32
|
+
*/
|
|
33
|
+
export const SELF_SCOPE_ID = 'me';
|
|
23
34
|
/**
|
|
24
35
|
* The artwork to display for an episode: its own {@link DisplaySnapshot.imageUrl} if present, otherwise
|
|
25
36
|
* the {@link DisplaySnapshot.feedImageUrl feed cover}, otherwise `undefined`.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,qDAAqD;AAErD;;;;;;;;GAQG;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mosaicast/plugin-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Versioned plugin contract for Mosaicast: the frontend PluginContext types, a Web Component base helper, an i18n helper, plus a test kit under the /testing subpath.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"test:watch": "vitest"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"jsdom": "^
|
|
36
|
+
"jsdom": "^30.0.1",
|
|
37
37
|
"typescript": "^7.0.2",
|
|
38
38
|
"vitest": "^4.1.10"
|
|
39
39
|
},
|