@biffo/cli 0.313.4 → 0.314.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/_skeletons/plugin-template/biffo.plugin.json +14 -2
- package/_skeletons/plugin-template/pyproject.toml +6 -0
- package/_skeletons/plugin-template/src/example_plugin/admin_app.py +50 -0
- package/_skeletons/plugin-template/src/example_plugin/user_app.py +31 -0
- package/_skeletons/plugin-template/tests/test_example_plugin_ingress_surfaces.py +119 -0
- package/_skeletons/plugin-template/uv.lock +39 -0
- package/_skeletons/plugin-template/web-admin/pnpm-lock.yaml +70 -59
- package/package.json +1 -1
|
@@ -80,8 +80,8 @@
|
|
|
80
80
|
}
|
|
81
81
|
],
|
|
82
82
|
"ui_components": [
|
|
83
|
-
{ "type": "nav-link", "label": "Example Plugin", "path": "/admin/example-plugin" },
|
|
84
|
-
{ "type": "page", "label": "Widgets", "path": "/admin/example-plugin/widgets" }
|
|
83
|
+
{ "type": "nav-link", "label": "Example Plugin", "path": "/admin/plugins/example-plugin" },
|
|
84
|
+
{ "type": "page", "label": "Widgets", "path": "/admin/plugins/example-plugin/widgets" }
|
|
85
85
|
],
|
|
86
86
|
"seed": {
|
|
87
87
|
"dir": "db/seed",
|
|
@@ -89,5 +89,17 @@
|
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
91
|
"biffo-plugin-sdk": "^1.0"
|
|
92
|
+
},
|
|
93
|
+
"user_ingress": {
|
|
94
|
+
"required_group": "founder",
|
|
95
|
+
"app": "example_plugin.user_app:app"
|
|
96
|
+
},
|
|
97
|
+
"admin_ingress": {
|
|
98
|
+
"required_group": "admin",
|
|
99
|
+
"app": "example_plugin.admin_app:app"
|
|
100
|
+
},
|
|
101
|
+
"user_frontend": {
|
|
102
|
+
"dir": "web/dist",
|
|
103
|
+
"required_group": "founder"
|
|
92
104
|
}
|
|
93
105
|
}
|
|
@@ -15,6 +15,12 @@ dependencies = [
|
|
|
15
15
|
"biffo-plugin-sdk>=1.0,<2.0",
|
|
16
16
|
"aws-lambda-powertools[tracer]>=3.4.0",
|
|
17
17
|
"httpx>=0.28.1",
|
|
18
|
+
# ASGI apps for the `user_ingress`/`admin_ingress` surfaces (ADR-0021) —
|
|
19
|
+
# the shared plugin host imports and mounts `<module>:app` directly, so this
|
|
20
|
+
# is the only new runtime dependency the two placeholder apps need (no
|
|
21
|
+
# mangum/pyjwt: the host provides the Lambda entry and enforces
|
|
22
|
+
# `required_group` itself — see user_app.py's docstring).
|
|
23
|
+
"fastapi>=0.115.0",
|
|
18
24
|
]
|
|
19
25
|
|
|
20
26
|
[dependency-groups]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Placeholder ASGI app backing this plugin's `admin_ingress` surface (ADR-0021).
|
|
2
|
+
|
|
3
|
+
`biffo.plugin.json`'s `admin_ingress.app` names this module's `app` object. The
|
|
4
|
+
**shared plugin host** imports it, provides the Lambda entry, and mounts it at
|
|
5
|
+
`/api/v1/plugins/<name>/admin/*`, enforcing `admin_ingress.required_group`
|
|
6
|
+
(ADR-0011) before a request ever reaches here — see `user_app.py`'s docstring
|
|
7
|
+
for why this file does no auth of its own.
|
|
8
|
+
|
|
9
|
+
**This is also `web-admin/`'s one reader (biffo-template#2008).** The skeleton
|
|
10
|
+
shipped a full admin frontend at `web-admin/` that no manifest field referenced
|
|
11
|
+
— an orphan directory nothing would ever build or serve. `AdminIngress` in the
|
|
12
|
+
SDK is explicitly "the plugin's admin-gated API and optional static UI bundle":
|
|
13
|
+
unlike `user_frontend` (a separate declarative `dir`, served directly by the
|
|
14
|
+
host with no plugin code involved), the admin surface's static bundle is served
|
|
15
|
+
*by the app this field names* — `web-admin/`'s own `vite.config.ts` already
|
|
16
|
+
targets exactly this mount point (`base:
|
|
17
|
+
'/api/v1/plugins/example-plugin/admin/'`).
|
|
18
|
+
|
|
19
|
+
`web-admin/dist/` is the Vite build output — gitignored, and not built by this
|
|
20
|
+
repo's CI (that wiring is follow-up work; #2008's scope is declaring the
|
|
21
|
+
surfaces, not shipping the built bundle, mirroring `user_frontend.dir` above
|
|
22
|
+
pointing at `web/dist` before that directory exists either — see #2009). The
|
|
23
|
+
mount below is skipped when `dist/` is absent, so a fresh checkout and `pytest`
|
|
24
|
+
need no build step and no edits (this issue's "done when" criterion) — once
|
|
25
|
+
`web-admin` is built, dropping its `dist/` in place is enough to serve it, with
|
|
26
|
+
no further code change.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
from fastapi import FastAPI
|
|
34
|
+
from fastapi.staticfiles import StaticFiles
|
|
35
|
+
|
|
36
|
+
app = FastAPI(title="example-plugin admin ingress")
|
|
37
|
+
|
|
38
|
+
# src/example_plugin/admin_app.py -> src/example_plugin -> src -> repo root
|
|
39
|
+
# (plugin root, where web-admin/ lives alongside biffo.plugin.json).
|
|
40
|
+
WEB_ADMIN_DIST = Path(__file__).resolve().parent.parent.parent / "web-admin" / "dist"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.get("/ping")
|
|
44
|
+
def ping() -> dict[str, str]:
|
|
45
|
+
"""Identifies the plugin, so the mount can be proven real rather than guessed at."""
|
|
46
|
+
return {"plugin": "example-plugin", "surface": "admin_ingress"}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if WEB_ADMIN_DIST.is_dir():
|
|
50
|
+
app.mount("/", StaticFiles(directory=str(WEB_ADMIN_DIST), html=True), name="web-admin")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Placeholder ASGI app backing this plugin's `user_ingress` surface (ADR-0021).
|
|
2
|
+
|
|
3
|
+
`biffo.plugin.json`'s `user_ingress.app` names this module's `app` object. The
|
|
4
|
+
**shared plugin host** imports it, provides the Lambda entry, and mounts it at
|
|
5
|
+
`/api/v1/plugins/<name>/*` — a plugin declaring `user_ingress` ships no Lambda
|
|
6
|
+
handler and no infrastructure of its own for this surface (see `terraform/`:
|
|
7
|
+
nothing here needs a per-plugin resource).
|
|
8
|
+
|
|
9
|
+
**No auth in this file, on purpose.** The host enforces `user_ingress.required_group`
|
|
10
|
+
(ADR-0011) before a request ever reaches a mounted app — see
|
|
11
|
+
`biffo_plugin_sdk.user_serving`'s module docstring: its `require_group` dependency
|
|
12
|
+
is only for an `isolated: true` plugin running in its own Lambda outside the
|
|
13
|
+
shared host. Adding a second check here would be redundant at best and a
|
|
14
|
+
divergent enforcement path at worst.
|
|
15
|
+
|
|
16
|
+
This is intentionally a placeholder (biffo-template#2008): one route that
|
|
17
|
+
identifies the plugin, enough to prove the mount is real, not enough to be
|
|
18
|
+
mistaken for a feature. Replace it with your own user-facing routes.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from fastapi import FastAPI
|
|
24
|
+
|
|
25
|
+
app = FastAPI(title="example-plugin user ingress")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@app.get("/ping")
|
|
29
|
+
def ping() -> dict[str, str]:
|
|
30
|
+
"""Identifies the plugin, so the mount can be proven real rather than guessed at."""
|
|
31
|
+
return {"plugin": "example-plugin", "surface": "user_ingress"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""Pins the three platform surfaces `biffo.plugin.json` declares (biffo-template#2008).
|
|
2
|
+
|
|
3
|
+
Before this, `_skeletons/plugin-template` declared none of `user_ingress`,
|
|
4
|
+
`admin_ingress` or `user_frontend` — the platform already serves all three
|
|
5
|
+
(the working reference is `keiranholloway/biffo-plugin-ideation`'s manifest),
|
|
6
|
+
but every scaffolded plugin started life exposing none of them. This test
|
|
7
|
+
guards three things at once:
|
|
8
|
+
|
|
9
|
+
1. the manifest actually validates against the SDK's real `PluginManifest`
|
|
10
|
+
(`extra="forbid"`, so a typo in a block's keys fails loudly rather than
|
|
11
|
+
silently dropping the surface — see `README.md`'s "Manifest validation"
|
|
12
|
+
section for why that model, not `registry-schema.json`, is authoritative);
|
|
13
|
+
2. each `*_ingress.app` reference actually resolves to a real, importable ASGI
|
|
14
|
+
app — not merely a string that looks right; and
|
|
15
|
+
3. each placeholder app answers with something that identifies the plugin,
|
|
16
|
+
so the mount is real rather than guessed at (this issue's own "done when").
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import importlib
|
|
22
|
+
|
|
23
|
+
from biffo_plugin_sdk.plugin import load_manifest
|
|
24
|
+
from fastapi import FastAPI
|
|
25
|
+
from fastapi.testclient import TestClient
|
|
26
|
+
|
|
27
|
+
from example_plugin.manifest import MANIFEST_PATH
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _resolve_app(app_ref: str) -> FastAPI:
|
|
31
|
+
"""Resolve a manifest `*_ingress.app` string ('<module>:<attr>') the same
|
|
32
|
+
way the shared plugin host would — a plain dynamic import, not a literal
|
|
33
|
+
reference to this test's own imports, so a manifest string that drifted
|
|
34
|
+
from the real module path would be caught here rather than passing by
|
|
35
|
+
coincidence."""
|
|
36
|
+
module_name, _, attr = app_ref.partition(":")
|
|
37
|
+
module = importlib.import_module(module_name)
|
|
38
|
+
return getattr(module, attr)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TestManifestDeclaresAllThreeSurfaces:
|
|
42
|
+
def test_manifest_validates_and_declares_user_ingress(self) -> None:
|
|
43
|
+
manifest = load_manifest(MANIFEST_PATH)
|
|
44
|
+
assert manifest.user_ingress is not None
|
|
45
|
+
assert manifest.user_ingress.required_group == "founder"
|
|
46
|
+
assert manifest.user_ingress.app == "example_plugin.user_app:app"
|
|
47
|
+
|
|
48
|
+
def test_manifest_declares_admin_ingress(self) -> None:
|
|
49
|
+
manifest = load_manifest(MANIFEST_PATH)
|
|
50
|
+
assert manifest.admin_ingress is not None
|
|
51
|
+
assert manifest.admin_ingress.required_group == "admin"
|
|
52
|
+
assert manifest.admin_ingress.app == "example_plugin.admin_app:app"
|
|
53
|
+
|
|
54
|
+
def test_manifest_declares_user_frontend(self) -> None:
|
|
55
|
+
manifest = load_manifest(MANIFEST_PATH)
|
|
56
|
+
assert manifest.user_frontend is not None
|
|
57
|
+
assert manifest.user_frontend.dir == "web/dist"
|
|
58
|
+
assert manifest.user_frontend.required_group == "founder"
|
|
59
|
+
|
|
60
|
+
def test_ui_components_no_longer_point_at_a_dead_admin_path(self) -> None:
|
|
61
|
+
"""The old `/admin/example-plugin` paths matched none of the three real
|
|
62
|
+
surfaces (this issue's own finding) — pin that they now sit under the
|
|
63
|
+
portal's real installed-plugin route instead."""
|
|
64
|
+
manifest = load_manifest(MANIFEST_PATH)
|
|
65
|
+
paths = {c.path for c in manifest.ui_components}
|
|
66
|
+
assert paths == {
|
|
67
|
+
"/admin/plugins/example-plugin",
|
|
68
|
+
"/admin/plugins/example-plugin/widgets",
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class TestIngressAppsResolveAndIdentifyThePlugin:
|
|
73
|
+
def test_user_ingress_app_resolves_and_answers(self) -> None:
|
|
74
|
+
manifest = load_manifest(MANIFEST_PATH)
|
|
75
|
+
assert manifest.user_ingress is not None
|
|
76
|
+
app = _resolve_app(manifest.user_ingress.app)
|
|
77
|
+
|
|
78
|
+
response = TestClient(app).get("/ping")
|
|
79
|
+
|
|
80
|
+
assert response.status_code == 200
|
|
81
|
+
assert response.json() == {"plugin": "example-plugin", "surface": "user_ingress"}
|
|
82
|
+
|
|
83
|
+
def test_admin_ingress_app_resolves_and_answers(self) -> None:
|
|
84
|
+
manifest = load_manifest(MANIFEST_PATH)
|
|
85
|
+
assert manifest.admin_ingress is not None
|
|
86
|
+
app = _resolve_app(manifest.admin_ingress.app)
|
|
87
|
+
|
|
88
|
+
response = TestClient(app).get("/ping")
|
|
89
|
+
|
|
90
|
+
assert response.status_code == 200
|
|
91
|
+
assert response.json() == {"plugin": "example-plugin", "surface": "admin_ingress"}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class TestAdminIngressWebAdminOrphanResolution:
|
|
95
|
+
"""`web-admin/` had no manifest field referencing it (this issue's own
|
|
96
|
+
finding). `admin_app.py` is now its one reader — these pin that the
|
|
97
|
+
reference is real (the directory `admin_app` looks for is exactly
|
|
98
|
+
`web-admin/`, not a typo'd sibling) and that a repo state with no built
|
|
99
|
+
`dist/` yet (true of this skeleton and every fresh checkout, since `dist/`
|
|
100
|
+
is gitignored and nothing builds it here — see admin_app.py's docstring)
|
|
101
|
+
still imports and serves cleanly rather than raising at import time.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
def test_web_admin_dist_path_points_at_the_real_directory(self) -> None:
|
|
105
|
+
from example_plugin.admin_app import WEB_ADMIN_DIST
|
|
106
|
+
|
|
107
|
+
assert WEB_ADMIN_DIST.parent.name == "web-admin"
|
|
108
|
+
assert WEB_ADMIN_DIST.name == "dist"
|
|
109
|
+
assert WEB_ADMIN_DIST.parent.is_dir(), "web-admin/ itself must still exist"
|
|
110
|
+
|
|
111
|
+
def test_static_mount_is_skipped_when_dist_is_absent(self) -> None:
|
|
112
|
+
from example_plugin.admin_app import WEB_ADMIN_DIST, app
|
|
113
|
+
|
|
114
|
+
assert not WEB_ADMIN_DIST.is_dir(), (
|
|
115
|
+
"this test asserts the no-build-yet behaviour; if dist/ has been "
|
|
116
|
+
"built locally, the skip path this test pins is not being exercised"
|
|
117
|
+
)
|
|
118
|
+
response = TestClient(app).get("/some/never-built/asset.js")
|
|
119
|
+
assert response.status_code == 404
|
|
@@ -2,6 +2,15 @@ version = 1
|
|
|
2
2
|
revision = 3
|
|
3
3
|
requires-python = ">=3.13"
|
|
4
4
|
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "annotated-doc"
|
|
7
|
+
version = "0.0.5"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" }
|
|
10
|
+
wheels = [
|
|
11
|
+
{ url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" },
|
|
12
|
+
]
|
|
13
|
+
|
|
5
14
|
[[package]]
|
|
6
15
|
name = "annotated-types"
|
|
7
16
|
version = "0.8.0"
|
|
@@ -70,6 +79,7 @@ source = { editable = "." }
|
|
|
70
79
|
dependencies = [
|
|
71
80
|
{ name = "aws-lambda-powertools", extra = ["tracer"] },
|
|
72
81
|
{ name = "biffo-plugin-sdk" },
|
|
82
|
+
{ name = "fastapi" },
|
|
73
83
|
{ name = "httpx" },
|
|
74
84
|
]
|
|
75
85
|
|
|
@@ -88,6 +98,7 @@ dev = [
|
|
|
88
98
|
requires-dist = [
|
|
89
99
|
{ name = "aws-lambda-powertools", extras = ["tracer"], specifier = ">=3.4.0" },
|
|
90
100
|
{ name = "biffo-plugin-sdk", specifier = ">=1.0,<2.0" },
|
|
101
|
+
{ name = "fastapi", specifier = ">=0.115.0" },
|
|
91
102
|
{ name = "httpx", specifier = ">=0.28.1" },
|
|
92
103
|
]
|
|
93
104
|
|
|
@@ -398,6 +409,22 @@ wheels = [
|
|
|
398
409
|
{ url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" },
|
|
399
410
|
]
|
|
400
411
|
|
|
412
|
+
[[package]]
|
|
413
|
+
name = "fastapi"
|
|
414
|
+
version = "0.141.1"
|
|
415
|
+
source = { registry = "https://pypi.org/simple" }
|
|
416
|
+
dependencies = [
|
|
417
|
+
{ name = "annotated-doc" },
|
|
418
|
+
{ name = "pydantic" },
|
|
419
|
+
{ name = "starlette" },
|
|
420
|
+
{ name = "typing-extensions" },
|
|
421
|
+
{ name = "typing-inspection" },
|
|
422
|
+
]
|
|
423
|
+
sdist = { url = "https://files.pythonhosted.org/packages/8a/02/91e3416a8fdd715abb903a952a6bec7cdd8d14eed55d415fc8595524c319/fastapi-0.141.1.tar.gz", hash = "sha256:e8822fc40db1e1858054d7a949a888695bc9bdce70139178e33bd2871a453ca1", size = 425799, upload-time = "2026-07-29T17:18:05.568Z" }
|
|
424
|
+
wheels = [
|
|
425
|
+
{ url = "https://files.pythonhosted.org/packages/cb/03/10388a42375ee7e4ac9b94eb2c5c569c8b5795e377e701c9ac3ad63de890/fastapi-0.141.1-py3-none-any.whl", hash = "sha256:bfb91aa2d334c61cb35ba9a116fc123b3d3df31640b801cf57a7a78ec3f603b3", size = 131954, upload-time = "2026-07-29T17:18:04.364Z" },
|
|
426
|
+
]
|
|
427
|
+
|
|
401
428
|
[[package]]
|
|
402
429
|
name = "filelock"
|
|
403
430
|
version = "3.32.3"
|
|
@@ -1005,6 +1032,18 @@ wheels = [
|
|
|
1005
1032
|
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" },
|
|
1006
1033
|
]
|
|
1007
1034
|
|
|
1035
|
+
[[package]]
|
|
1036
|
+
name = "starlette"
|
|
1037
|
+
version = "1.6.0"
|
|
1038
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1039
|
+
dependencies = [
|
|
1040
|
+
{ name = "anyio" },
|
|
1041
|
+
]
|
|
1042
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b5/b4/205b0d5241d934e8add0c38aa924c4f9fb7330834ff11e5444db964ec3f9/starlette-1.6.0.tar.gz", hash = "sha256:d4e3ac5e546444960c710297a3c9fc3f7ebae1b7e963f3d36173b49da535be9b", size = 2716969, upload-time = "2026-08-08T18:27:57.512Z" }
|
|
1043
|
+
wheels = [
|
|
1044
|
+
{ url = "https://files.pythonhosted.org/packages/c8/cb/6a6a47d5b464bd08695d254f3da6e7986cc70c9fa5d778eda57538edfe56/starlette-1.6.0-py3-none-any.whl", hash = "sha256:a86dd39d14bb45f85a3d18525215a9ef0cfd1f192ac793220e72598c90335f0c", size = 75969, upload-time = "2026-08-08T18:27:56.196Z" },
|
|
1045
|
+
]
|
|
1046
|
+
|
|
1008
1047
|
[[package]]
|
|
1009
1048
|
name = "tomli"
|
|
1010
1049
|
version = "2.4.1"
|
|
@@ -67,7 +67,7 @@ importers:
|
|
|
67
67
|
version: 6.4.3(@types/node@26.2.0)
|
|
68
68
|
vitest:
|
|
69
69
|
specifier: ^4.1.0
|
|
70
|
-
version: 4.1.
|
|
70
|
+
version: 4.1.11(@types/node@26.2.0)(jsdom@30.0.1)(vite@6.4.3(@types/node@26.2.0))
|
|
71
71
|
|
|
72
72
|
packages:
|
|
73
73
|
|
|
@@ -461,6 +461,9 @@ packages:
|
|
|
461
461
|
'@jridgewell/sourcemap-codec@1.5.5':
|
|
462
462
|
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
|
463
463
|
|
|
464
|
+
'@jridgewell/sourcemap-codec@1.6.0':
|
|
465
|
+
resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
|
|
466
|
+
|
|
464
467
|
'@jridgewell/trace-mapping@0.3.31':
|
|
465
468
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
|
466
469
|
|
|
@@ -740,11 +743,11 @@ packages:
|
|
|
740
743
|
peerDependencies:
|
|
741
744
|
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
|
|
742
745
|
|
|
743
|
-
'@vitest/expect@4.1.
|
|
744
|
-
resolution: {integrity: sha512-
|
|
746
|
+
'@vitest/expect@4.1.11':
|
|
747
|
+
resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==}
|
|
745
748
|
|
|
746
|
-
'@vitest/mocker@4.1.
|
|
747
|
-
resolution: {integrity: sha512-
|
|
749
|
+
'@vitest/mocker@4.1.11':
|
|
750
|
+
resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==}
|
|
748
751
|
peerDependencies:
|
|
749
752
|
msw: ^2.4.9
|
|
750
753
|
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
|
@@ -754,20 +757,20 @@ packages:
|
|
|
754
757
|
vite:
|
|
755
758
|
optional: true
|
|
756
759
|
|
|
757
|
-
'@vitest/pretty-format@4.1.
|
|
758
|
-
resolution: {integrity: sha512-
|
|
760
|
+
'@vitest/pretty-format@4.1.11':
|
|
761
|
+
resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==}
|
|
759
762
|
|
|
760
|
-
'@vitest/runner@4.1.
|
|
761
|
-
resolution: {integrity: sha512-
|
|
763
|
+
'@vitest/runner@4.1.11':
|
|
764
|
+
resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==}
|
|
762
765
|
|
|
763
|
-
'@vitest/snapshot@4.1.
|
|
764
|
-
resolution: {integrity: sha512-
|
|
766
|
+
'@vitest/snapshot@4.1.11':
|
|
767
|
+
resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==}
|
|
765
768
|
|
|
766
|
-
'@vitest/spy@4.1.
|
|
767
|
-
resolution: {integrity: sha512-
|
|
769
|
+
'@vitest/spy@4.1.11':
|
|
770
|
+
resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==}
|
|
768
771
|
|
|
769
|
-
'@vitest/utils@4.1.
|
|
770
|
-
resolution: {integrity: sha512-
|
|
772
|
+
'@vitest/utils@4.1.11':
|
|
773
|
+
resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==}
|
|
771
774
|
|
|
772
775
|
acorn-jsx@5.3.2:
|
|
773
776
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
|
@@ -913,8 +916,8 @@ packages:
|
|
|
913
916
|
resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==}
|
|
914
917
|
engines: {node: '>=20.19.0'}
|
|
915
918
|
|
|
916
|
-
es-module-lexer@2.3.
|
|
917
|
-
resolution: {integrity: sha512-
|
|
919
|
+
es-module-lexer@2.3.2:
|
|
920
|
+
resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==}
|
|
918
921
|
|
|
919
922
|
esbuild@0.25.12:
|
|
920
923
|
resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==}
|
|
@@ -1190,8 +1193,8 @@ packages:
|
|
|
1190
1193
|
resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==}
|
|
1191
1194
|
engines: {node: '>=18'}
|
|
1192
1195
|
|
|
1193
|
-
obug@2.1
|
|
1194
|
-
resolution: {integrity: sha512-
|
|
1196
|
+
obug@2.2.1:
|
|
1197
|
+
resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==}
|
|
1195
1198
|
engines: {node: '>=12.20.0'}
|
|
1196
1199
|
|
|
1197
1200
|
optionator@0.9.4:
|
|
@@ -1231,6 +1234,10 @@ packages:
|
|
|
1231
1234
|
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
|
|
1232
1235
|
engines: {node: '>=12'}
|
|
1233
1236
|
|
|
1237
|
+
picomatch@4.0.7:
|
|
1238
|
+
resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
|
|
1239
|
+
engines: {node: '>=12'}
|
|
1240
|
+
|
|
1234
1241
|
postcss@8.5.26:
|
|
1235
1242
|
resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
|
|
1236
1243
|
engines: {node: ^10 || ^12 || >=14}
|
|
@@ -1335,8 +1342,8 @@ packages:
|
|
|
1335
1342
|
tinybench@2.9.0:
|
|
1336
1343
|
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
|
|
1337
1344
|
|
|
1338
|
-
tinyexec@1.3.
|
|
1339
|
-
resolution: {integrity: sha512-
|
|
1345
|
+
tinyexec@1.3.1:
|
|
1346
|
+
resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==}
|
|
1340
1347
|
engines: {node: '>=18'}
|
|
1341
1348
|
|
|
1342
1349
|
tinyglobby@0.2.17:
|
|
@@ -1452,20 +1459,20 @@ packages:
|
|
|
1452
1459
|
yaml:
|
|
1453
1460
|
optional: true
|
|
1454
1461
|
|
|
1455
|
-
vitest@4.1.
|
|
1456
|
-
resolution: {integrity: sha512-
|
|
1462
|
+
vitest@4.1.11:
|
|
1463
|
+
resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==}
|
|
1457
1464
|
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
|
|
1458
1465
|
hasBin: true
|
|
1459
1466
|
peerDependencies:
|
|
1460
1467
|
'@edge-runtime/vm': '*'
|
|
1461
1468
|
'@opentelemetry/api': ^1.9.0
|
|
1462
1469
|
'@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0
|
|
1463
|
-
'@vitest/browser-playwright': 4.1.
|
|
1464
|
-
'@vitest/browser-preview': 4.1.
|
|
1465
|
-
'@vitest/browser-webdriverio': 4.1.
|
|
1466
|
-
'@vitest/coverage-istanbul': 4.1.
|
|
1467
|
-
'@vitest/coverage-v8': 4.1.
|
|
1468
|
-
'@vitest/ui': 4.1.
|
|
1470
|
+
'@vitest/browser-playwright': 4.1.11
|
|
1471
|
+
'@vitest/browser-preview': 4.1.11
|
|
1472
|
+
'@vitest/browser-webdriverio': 4.1.11
|
|
1473
|
+
'@vitest/coverage-istanbul': 4.1.11
|
|
1474
|
+
'@vitest/coverage-v8': 4.1.11
|
|
1475
|
+
'@vitest/ui': 4.1.11
|
|
1469
1476
|
happy-dom: '*'
|
|
1470
1477
|
jsdom: '*'
|
|
1471
1478
|
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
|
@@ -1887,6 +1894,8 @@ snapshots:
|
|
|
1887
1894
|
|
|
1888
1895
|
'@jridgewell/sourcemap-codec@1.5.5': {}
|
|
1889
1896
|
|
|
1897
|
+
'@jridgewell/sourcemap-codec@1.6.0': {}
|
|
1898
|
+
|
|
1890
1899
|
'@jridgewell/trace-mapping@0.3.31':
|
|
1891
1900
|
dependencies:
|
|
1892
1901
|
'@jridgewell/resolve-uri': 3.1.2
|
|
@@ -2162,44 +2171,44 @@ snapshots:
|
|
|
2162
2171
|
transitivePeerDependencies:
|
|
2163
2172
|
- supports-color
|
|
2164
2173
|
|
|
2165
|
-
'@vitest/expect@4.1.
|
|
2174
|
+
'@vitest/expect@4.1.11':
|
|
2166
2175
|
dependencies:
|
|
2167
2176
|
'@standard-schema/spec': 1.1.0
|
|
2168
2177
|
'@types/chai': 5.2.3
|
|
2169
|
-
'@vitest/spy': 4.1.
|
|
2170
|
-
'@vitest/utils': 4.1.
|
|
2178
|
+
'@vitest/spy': 4.1.11
|
|
2179
|
+
'@vitest/utils': 4.1.11
|
|
2171
2180
|
chai: 6.2.2
|
|
2172
2181
|
tinyrainbow: 3.1.1
|
|
2173
2182
|
|
|
2174
|
-
'@vitest/mocker@4.1.
|
|
2183
|
+
'@vitest/mocker@4.1.11(vite@6.4.3(@types/node@26.2.0))':
|
|
2175
2184
|
dependencies:
|
|
2176
|
-
'@vitest/spy': 4.1.
|
|
2185
|
+
'@vitest/spy': 4.1.11
|
|
2177
2186
|
estree-walker: 3.0.3
|
|
2178
2187
|
magic-string: 0.30.21
|
|
2179
2188
|
optionalDependencies:
|
|
2180
2189
|
vite: 6.4.3(@types/node@26.2.0)
|
|
2181
2190
|
|
|
2182
|
-
'@vitest/pretty-format@4.1.
|
|
2191
|
+
'@vitest/pretty-format@4.1.11':
|
|
2183
2192
|
dependencies:
|
|
2184
2193
|
tinyrainbow: 3.1.1
|
|
2185
2194
|
|
|
2186
|
-
'@vitest/runner@4.1.
|
|
2195
|
+
'@vitest/runner@4.1.11':
|
|
2187
2196
|
dependencies:
|
|
2188
|
-
'@vitest/utils': 4.1.
|
|
2197
|
+
'@vitest/utils': 4.1.11
|
|
2189
2198
|
pathe: 2.0.3
|
|
2190
2199
|
|
|
2191
|
-
'@vitest/snapshot@4.1.
|
|
2200
|
+
'@vitest/snapshot@4.1.11':
|
|
2192
2201
|
dependencies:
|
|
2193
|
-
'@vitest/pretty-format': 4.1.
|
|
2194
|
-
'@vitest/utils': 4.1.
|
|
2202
|
+
'@vitest/pretty-format': 4.1.11
|
|
2203
|
+
'@vitest/utils': 4.1.11
|
|
2195
2204
|
magic-string: 0.30.21
|
|
2196
2205
|
pathe: 2.0.3
|
|
2197
2206
|
|
|
2198
|
-
'@vitest/spy@4.1.
|
|
2207
|
+
'@vitest/spy@4.1.11': {}
|
|
2199
2208
|
|
|
2200
|
-
'@vitest/utils@4.1.
|
|
2209
|
+
'@vitest/utils@4.1.11':
|
|
2201
2210
|
dependencies:
|
|
2202
|
-
'@vitest/pretty-format': 4.1.
|
|
2211
|
+
'@vitest/pretty-format': 4.1.11
|
|
2203
2212
|
convert-source-map: 2.0.0
|
|
2204
2213
|
tinyrainbow: 3.1.1
|
|
2205
2214
|
|
|
@@ -2331,7 +2340,7 @@ snapshots:
|
|
|
2331
2340
|
|
|
2332
2341
|
entities@8.0.0: {}
|
|
2333
2342
|
|
|
2334
|
-
es-module-lexer@2.3.
|
|
2343
|
+
es-module-lexer@2.3.2: {}
|
|
2335
2344
|
|
|
2336
2345
|
esbuild@0.25.12:
|
|
2337
2346
|
optionalDependencies:
|
|
@@ -2590,7 +2599,7 @@ snapshots:
|
|
|
2590
2599
|
|
|
2591
2600
|
magic-string@0.30.21:
|
|
2592
2601
|
dependencies:
|
|
2593
|
-
'@jridgewell/sourcemap-codec': 1.
|
|
2602
|
+
'@jridgewell/sourcemap-codec': 1.6.0
|
|
2594
2603
|
|
|
2595
2604
|
mdn-data@2.27.1: {}
|
|
2596
2605
|
|
|
@@ -2616,7 +2625,7 @@ snapshots:
|
|
|
2616
2625
|
|
|
2617
2626
|
node-releases@2.0.53: {}
|
|
2618
2627
|
|
|
2619
|
-
obug@2.1
|
|
2628
|
+
obug@2.2.1: {}
|
|
2620
2629
|
|
|
2621
2630
|
optionator@0.9.4:
|
|
2622
2631
|
dependencies:
|
|
@@ -2653,6 +2662,8 @@ snapshots:
|
|
|
2653
2662
|
|
|
2654
2663
|
picomatch@4.0.5: {}
|
|
2655
2664
|
|
|
2665
|
+
picomatch@4.0.7: {}
|
|
2666
|
+
|
|
2656
2667
|
postcss@8.5.26:
|
|
2657
2668
|
dependencies:
|
|
2658
2669
|
nanoid: 3.3.18
|
|
@@ -2759,7 +2770,7 @@ snapshots:
|
|
|
2759
2770
|
|
|
2760
2771
|
tinybench@2.9.0: {}
|
|
2761
2772
|
|
|
2762
|
-
tinyexec@1.3.
|
|
2773
|
+
tinyexec@1.3.1: {}
|
|
2763
2774
|
|
|
2764
2775
|
tinyglobby@0.2.17:
|
|
2765
2776
|
dependencies:
|
|
@@ -2837,24 +2848,24 @@ snapshots:
|
|
|
2837
2848
|
'@types/node': 26.2.0
|
|
2838
2849
|
fsevents: 2.3.3
|
|
2839
2850
|
|
|
2840
|
-
vitest@4.1.
|
|
2851
|
+
vitest@4.1.11(@types/node@26.2.0)(jsdom@30.0.1)(vite@6.4.3(@types/node@26.2.0)):
|
|
2841
2852
|
dependencies:
|
|
2842
|
-
'@vitest/expect': 4.1.
|
|
2843
|
-
'@vitest/mocker': 4.1.
|
|
2844
|
-
'@vitest/pretty-format': 4.1.
|
|
2845
|
-
'@vitest/runner': 4.1.
|
|
2846
|
-
'@vitest/snapshot': 4.1.
|
|
2847
|
-
'@vitest/spy': 4.1.
|
|
2848
|
-
'@vitest/utils': 4.1.
|
|
2849
|
-
es-module-lexer: 2.3.
|
|
2853
|
+
'@vitest/expect': 4.1.11
|
|
2854
|
+
'@vitest/mocker': 4.1.11(vite@6.4.3(@types/node@26.2.0))
|
|
2855
|
+
'@vitest/pretty-format': 4.1.11
|
|
2856
|
+
'@vitest/runner': 4.1.11
|
|
2857
|
+
'@vitest/snapshot': 4.1.11
|
|
2858
|
+
'@vitest/spy': 4.1.11
|
|
2859
|
+
'@vitest/utils': 4.1.11
|
|
2860
|
+
es-module-lexer: 2.3.2
|
|
2850
2861
|
expect-type: 1.4.0
|
|
2851
2862
|
magic-string: 0.30.21
|
|
2852
|
-
obug: 2.1
|
|
2863
|
+
obug: 2.2.1
|
|
2853
2864
|
pathe: 2.0.3
|
|
2854
|
-
picomatch: 4.0.
|
|
2865
|
+
picomatch: 4.0.7
|
|
2855
2866
|
std-env: 4.2.0
|
|
2856
2867
|
tinybench: 2.9.0
|
|
2857
|
-
tinyexec: 1.3.
|
|
2868
|
+
tinyexec: 1.3.1
|
|
2858
2869
|
tinyglobby: 0.2.17
|
|
2859
2870
|
tinyrainbow: 3.1.1
|
|
2860
2871
|
vite: 6.4.3(@types/node@26.2.0)
|