@mosaicast/plugin-sdk 0.9.0 → 0.9.1
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 +37 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,9 @@ The contract version is a **single SemVer anchor** mirrored in four places that
|
|
|
33
33
|
**How the host matches it:** core compares `major.minor` **exactly**. A plugin declaring `0.3.x` is
|
|
34
34
|
rejected the moment the host runs `0.7.0` — with the reason shown in the admin log viewer. While the SDK
|
|
35
35
|
is pre-1.0 a breaking change is therefore a **minor** bump (`0.6.0` → `0.7.0`), not a major one; from
|
|
36
|
-
`1.0.0` on, normal SemVer applies and breaking means major.
|
|
36
|
+
`1.0.0` on, normal SemVer applies and breaking means major. **The patch floats** — a plugin declaring
|
|
37
|
+
`0.9.0` loads on a `0.9.1` host, which is what makes a purely additive release (a new optional extension
|
|
38
|
+
point, a test double) cheap: it rejects nothing already installed.
|
|
37
39
|
|
|
38
40
|
## Build & test
|
|
39
41
|
```bash
|
|
@@ -49,8 +51,8 @@ npm ci && npm run build # TypeScript: src → dist (.js + .d.ts)
|
|
|
49
51
|
- Released: from **GitHub Packages** (see below).
|
|
50
52
|
```kotlin
|
|
51
53
|
dependencies {
|
|
52
|
-
compileOnly("dev.mosaicast:plugin-api:0.
|
|
53
|
-
testImplementation("dev.mosaicast:plugin-testkit:0.
|
|
54
|
+
compileOnly("dev.mosaicast:plugin-api:0.9.1") // contract, provided by the host
|
|
55
|
+
testImplementation("dev.mosaicast:plugin-testkit:0.9.1") // test doubles only
|
|
54
56
|
}
|
|
55
57
|
```
|
|
56
58
|
Sources + Javadoc JARs give IDE hover docs automatically.
|
|
@@ -394,7 +396,8 @@ ctx.route.navigate('index', { replace: true }); // no back-button step (ta
|
|
|
394
396
|
- **Do not reach past this handle.** `history.pushState` plus a synthetic `popstate` happens to work
|
|
395
397
|
against the host's current router and is not part of the contract.
|
|
396
398
|
- Pair it with `ShareMetadataProvider` (OpenGraph per subpath) and `SitemapProvider` on the backend so the
|
|
397
|
-
URLs you navigate to also preview and index properly.
|
|
399
|
+
URLs you navigate to also preview and index properly — and with `PageRouteProvider` (since 0.9.1) so the
|
|
400
|
+
ones that do *not* exist answer 404 instead of a 200 with a not-found view in it.
|
|
398
401
|
|
|
399
402
|
### Reading the query, and matching a route (since 0.9.0)
|
|
400
403
|
|
|
@@ -568,9 +571,9 @@ nothing to catch it. Note where the two *legitimately* diverge: `path`, `icon` a
|
|
|
568
571
|
between them, but the menu **label cannot be translated** — core has no plugin catalogs — while your
|
|
569
572
|
in-page tab can.
|
|
570
573
|
|
|
571
|
-
## Optional extension points — `SearchProvider
|
|
574
|
+
## Optional extension points — `SearchProvider`, `UserDataHandler`, `PageRouteProvider`
|
|
572
575
|
|
|
573
|
-
|
|
576
|
+
All three are `ExtensionPoint`s a plugin MAY implement alongside `PluginBackend`, like `SitemapProvider`. No
|
|
574
577
|
manifest declaration: not implementing one is how a plugin says it has nothing to contribute.
|
|
575
578
|
|
|
576
579
|
**`SearchProvider`** puts plugin content into the site's search, instead of each plugin growing a private
|
|
@@ -611,6 +614,30 @@ which one is a person. Handlers run *before* the account row goes, and **must be
|
|
|
611
614
|
deletion is retried. `UserDataHandlerHarness.eraseTwice(userId)` is that test, and it is the one authors
|
|
612
615
|
skip: the second call is the one that throws, during a retry, when the alternative is a half-done deletion.
|
|
613
616
|
|
|
617
|
+
**`PageRouteProvider`** (since 0.9.1) is how a plugin's unknown subpaths become real 404s. Declare a `page`
|
|
618
|
+
slot and *every* subpath under `/p/<id>/` answers `200` — a page never written, a mistyped slug, the URL of
|
|
619
|
+
a page deleted last year — each rendering your not-found view inside a `200 OK`. §6.6 rules that soft-404
|
|
620
|
+
out for core's own routes, and the host cannot fix it alone: only the plugin knows whether a subpath is a
|
|
621
|
+
thing.
|
|
622
|
+
|
|
623
|
+
```java
|
|
624
|
+
public boolean hasRoute(String subpath) {
|
|
625
|
+
return subpath.isEmpty() || subpath.startsWith("_search/") || pages.exists(slugOf(subpath));
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**Not `ShareMetadataProvider`** — the tempting shortcut, and wrong: `_search/<term>` and `_admin` return an
|
|
630
|
+
empty `metaFor` *on purpose*, so reading "no share metadata" as "no page" would 404 working routes. Absent
|
|
631
|
+
means today's behaviour, the **root is a route** (`subpath` is empty there), it runs on a request so keep it
|
|
632
|
+
a lookup, and a provider that throws is logged and skipped and the route answers `200` — a broken plugin
|
|
633
|
+
must not turn a working page into a 404. It decides the status line only; the shell still renders the
|
|
634
|
+
not-found view. `PageRouteProviderHarness` asks about a handful of subpaths at once, root included:
|
|
635
|
+
|
|
636
|
+
```java
|
|
637
|
+
var routes = new PageRouteProviderHarness(new WikiRoutes(store)).check("glossary/kraken", "glossary/tpyo");
|
|
638
|
+
assertEquals(List.of("glossary/tpyo"), routes.notFound());
|
|
639
|
+
```
|
|
640
|
+
|
|
614
641
|
## Logging — `ctx.logger()` / `ctx.log()` (since 0.4.0)
|
|
615
642
|
|
|
616
643
|
```java
|
|
@@ -780,8 +807,10 @@ enforces the ceilings and the allow-list. A component that has only ever met a p
|
|
|
780
807
|
first refusal in front of a podcaster.
|
|
781
808
|
|
|
782
809
|
**The extension-point harnesses** (Java): `SearchProviderHarness` calls a provider once per role including
|
|
783
|
-
anonymous; `UserDataHandlerHarness.eraseTwice(userId)` proves erasure survives the host's retry
|
|
784
|
-
|
|
810
|
+
anonymous; `UserDataHandlerHarness.eraseTwice(userId)` proves erasure survives the host's retry;
|
|
811
|
+
`PageRouteProviderHarness.check(...)` answers which subpaths 404, always probing the plugin root. All three
|
|
812
|
+
are shown under
|
|
813
|
+
[Optional extension points](#optional-extension-points--searchprovider-userdatahandler-pagerouteprovider).
|
|
785
814
|
|
|
786
815
|
## Contributing
|
|
787
816
|
Contributions welcome — see [`CONTRIBUTING.md`](CONTRIBUTING.md). In short: `git commit -s` (DCO, required), SPDX header in new files, add tests.
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
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.9.
|
|
20
|
+
export declare const PLATFORM_API_VERSION: '0.9.1';
|
|
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
23
|
/**
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
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.9.
|
|
22
|
+
export const PLATFORM_API_VERSION = '0.9.1';
|
|
23
23
|
/**
|
|
24
24
|
* The id every `user` data path carries: the literal `me`, mirroring the Java `Scope.SELF_ID`.
|
|
25
25
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mosaicast/plugin-sdk",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
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": {
|