From 4f37c1bc694155904a5a27cfe576a31b750992f1 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 11 May 2026 09:59:48 +0200 Subject: [PATCH 01/15] =?UTF-8?q?Apply=20bootstrap-openbuilt=20=E2=80=94?= =?UTF-8?q?=20core=20implementation=20(tasks=201.1=E2=80=931.5,=202.1?= =?UTF-8?q?=E2=80=932.4,=203.1=E2=80=933.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Schemas (openbuilt-application-register capability): - Declare Application schema with manifest blob + slug + version + status - Add x-openregister-lifecycle (draft → published → archived) on Application — canonical ADR-031 example, no service class - Declare BuiltAppRoute schema for slug → applicationUuid index - Wire BuiltAppRoute upkeep via x-openregister-lifecycle on_transition (declarative path per design.md Decision 2 / Q1) - Declare HelloMessage seed schema Runtime (openbuilt-runtime capability): - Register GET /api/applications/{slug}/manifest route in appinfo/routes.php - ApplicationsController::getManifest — thin-glue resolver (slug → BuiltAppRoute → Application → manifest blob unwrapped). #[NoAdminRequired] + #[NoCSRFRequired] per design.md Decision 6 - BuilderHost.vue — nested CnAppRoot mount with key=slug, options.endpoint redirecting useAppManifest's backend fetch to the per-slug endpoint (workaround per design.md Decision 4 until chain spec #2 ships) - ApplicationEditor.vue — textarea-based manifest editor with validateManifest - src/router/index.js — /applications + /builder/:slug/:pathMatch(.*)? routes - src/manifests/placeholder.json — bundled placeholder skeleton for useAppManifest Seed (ADR-001): - SeedHelloWorld repair step — idempotent seed of canonical hello-world Application + manifest exercising index/detail/form pages + three sample HelloMessage objects - info.xml repair-steps — SeedHelloWorld runs after InitializeSettings Deferred to follow-up apply: tasks 4.x (verification), 5.x (tests), 6.x (docs), 7.x (i18n). Refs: openspec/changes/bootstrap-openbuilt/{proposal,specs,design,tasks}.md --- appinfo/info.xml | 2 + appinfo/routes.php | 7 + lib/Controller/ApplicationsController.php | 143 +++++++++++ lib/Repair/SeedHelloWorld.php | 229 ++++++++++++++++++ lib/Settings/openbuilt_register.json | 151 ++++++++++-- openspec/changes/bootstrap-openbuilt/tasks.md | 22 +- package-lock.json | 4 +- src/manifests/placeholder.json | 5 + src/router/index.js | 7 + src/views/ApplicationEditor.vue | 206 ++++++++++++++++ src/views/BuilderHost.vue | 63 +++++ 11 files changed, 812 insertions(+), 27 deletions(-) create mode 100644 lib/Controller/ApplicationsController.php create mode 100644 lib/Repair/SeedHelloWorld.php create mode 100644 src/manifests/placeholder.json create mode 100644 src/views/ApplicationEditor.vue create mode 100644 src/views/BuilderHost.vue diff --git a/appinfo/info.xml b/appinfo/info.xml index 418d8021..d64ff3d2 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -61,9 +61,11 @@ Vrij en open source onder de EUPL-1.2-licentie. OCA\OpenBuilt\Repair\InitializeSettings + OCA\OpenBuilt\Repair\SeedHelloWorld OCA\OpenBuilt\Repair\InitializeSettings + OCA\OpenBuilt\Repair\SeedHelloWorld diff --git a/appinfo/routes.php b/appinfo/routes.php index 689dc2f1..917b7251 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -16,6 +16,13 @@ // Health check endpoint. ['name' => 'health#index', 'url' => '/api/health', 'verb' => 'GET'], + // Manifest endpoint — returns the stored manifest JSON blob for a given virtual-app slug. + // Per ADR-016 routes.php is the only registration path; #[NoAdminRequired] is set on the + // controller method so auth-required-but-non-admin users can hit it (per design.md Decision 6). + // Slug matches the kebab-case pattern declared in openbuilt_register.json on the Application + // and BuiltAppRoute schemas (^[a-z0-9][a-z0-9-]*[a-z0-9]$, min 2 max 48 chars). + ['name' => 'applications#getManifest', 'url' => '/api/applications/{slug}/manifest', 'verb' => 'GET', 'requirements' => ['slug' => '[a-z0-9][a-z0-9-]*[a-z0-9]']], + // SPA catch-all — same controller as the index route; must use a distinct route name // (duplicate names replace the earlier route in Symfony, which breaks GET /). ['name' => 'dashboard#catchAll', 'url' => '/{path}', 'verb' => 'GET', 'requirements' => ['path' => '.+'], 'defaults' => ['path' => '']], diff --git a/lib/Controller/ApplicationsController.php b/lib/Controller/ApplicationsController.php new file mode 100644 index 00000000..66700751 --- /dev/null +++ b/lib/Controller/ApplicationsController.php @@ -0,0 +1,143 @@ + + * @copyright 2026 Conduction B.V. + * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * @version GIT: + * + * @link https://conduction.nl + */ + +declare(strict_types=1); + +namespace OCA\OpenBuilt\Controller; + +use OCA\OpenBuilt\AppInfo\Application; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\JSONResponse; +use OCP\IRequest; +use OCP\Server; +use Psr\Log\LoggerInterface; + +/** + * Controller for the OpenBuilt manifest endpoint. + */ +class ApplicationsController extends Controller +{ + /** + * Constructor. + * + * @param IRequest $request The current HTTP request + * @param LoggerInterface $logger PSR logger for diagnostics + * + * @return void + */ + public function __construct( + IRequest $request, + private readonly LoggerInterface $logger, + ) { + parent::__construct(appName: Application::APP_ID, request: $request); + + }//end __construct() + + + /** + * Return the stored manifest JSON blob for a given virtual-app slug. + * + * Lookup path: slug → BuiltAppRoute → applicationUuid → Application → + * manifest. The manifest is returned UNWRAPPED (no OR envelope) so + * useAppManifest in @conduction/nextcloud-vue consumes it directly. + * + * @param string $slug The virtual-app slug from the URL + * + * @return JSONResponse The manifest blob, or a 404 envelope when not found + */ + #[NoAdminRequired] + #[NoCSRFRequired] + public function getManifest(string $slug): JSONResponse + { + try { + // OpenRegister provides the OpenRegisterService and ObjectService via DI; + // resolve at request time to avoid hard-coupling at app boot when OR is + // not yet installed (per ADR-022). + $objectService = Server::get('OCA\\OpenRegister\\Service\\ObjectService'); + + // Step 1 — resolve slug → applicationUuid via the BuiltAppRoute index. + $routeResults = $objectService->getObjects( + register: 'openbuilt', + schema: 'built-app-route', + filters: ['slug' => $slug], + limit: 1 + ); + + if (empty($routeResults) === true) { + $this->logger->debug('OpenBuilt: no BuiltAppRoute found for slug='.$slug); + return new JSONResponse( + data: ['error' => 'not_found', 'message' => 'No published virtual app found for slug '.$slug], + statusCode: Http::STATUS_NOT_FOUND + ); + } + + $applicationUuid = ($routeResults[0]['applicationUuid'] ?? null); + + if ($applicationUuid === null) { + $this->logger->warning('OpenBuilt: BuiltAppRoute for slug '.$slug.' is missing applicationUuid'); + return new JSONResponse( + data: ['error' => 'inconsistent_state', 'message' => 'Route exists but has no applicationUuid'], + statusCode: Http::STATUS_INTERNAL_SERVER_ERROR + ); + } + + // Step 2 — load the Application object and return its manifest. + $application = $objectService->getObject( + register: 'openbuilt', + schema: 'application', + uuid: $applicationUuid + ); + + if ($application === null) { + $this->logger->warning('OpenBuilt: Application '.$applicationUuid.' (for slug '.$slug.') not found'); + return new JSONResponse( + data: ['error' => 'inconsistent_state', 'message' => 'Route points to an Application that does not exist'], + statusCode: Http::STATUS_INTERNAL_SERVER_ERROR + ); + } + + $manifest = ($application['manifest'] ?? null); + + if ($manifest === null) { + $this->logger->warning('OpenBuilt: Application '.$applicationUuid.' has no manifest property'); + return new JSONResponse( + data: ['error' => 'no_manifest', 'message' => 'Application has no manifest'], + statusCode: Http::STATUS_NOT_FOUND + ); + } + + // Return the manifest UNWRAPPED — useAppManifest expects the bare object. + return new JSONResponse(data: $manifest, statusCode: Http::STATUS_OK); + } catch (\Throwable $e) { + $this->logger->error('OpenBuilt: getManifest failed for slug '.$slug.': '.$e->getMessage(), ['exception' => $e]); + return new JSONResponse( + data: ['error' => 'internal_error', 'message' => 'Failed to resolve manifest'], + statusCode: Http::STATUS_INTERNAL_SERVER_ERROR + ); + }//end try + + }//end getManifest() +}//end class diff --git a/lib/Repair/SeedHelloWorld.php b/lib/Repair/SeedHelloWorld.php new file mode 100644 index 00000000..ccff4ac7 --- /dev/null +++ b/lib/Repair/SeedHelloWorld.php @@ -0,0 +1,229 @@ + + * @copyright 2026 Conduction B.V. + * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * @version GIT: + * + * @link https://conduction.nl + */ + +declare(strict_types=1); + +namespace OCA\OpenBuilt\Repair; + +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; +use OCP\Server; +use Psr\Log\LoggerInterface; + +/** + * Repair step that seeds the hello-world virtual app + sample messages. + */ +class SeedHelloWorld implements IRepairStep +{ + private const SEED_SLUG = 'hello-world'; + + /** + * Constructor. + * + * @param LoggerInterface $logger Logger for diagnostics + * + * @return void + */ + public function __construct( + private LoggerInterface $logger, + ) { + }//end __construct() + + + /** + * Get the name of this repair step. + * + * @return string + */ + public function getName(): string + { + return 'Seed the canonical hello-world virtual app and sample messages'; + }//end getName() + + + /** + * Run the repair step to seed the hello-world virtual app. + * + * @param IOutput $output The output interface for progress reporting + * + * @return void + */ + public function run(IOutput $output): void + { + $output->info('Seeding hello-world virtual app...'); + + try { + $objectService = Server::get('OCA\\OpenRegister\\Service\\ObjectService'); + } catch (\Throwable $e) { + $output->warning('OpenRegister not available; skipping seed.'); + $this->logger->warning( + 'OpenBuilt: SeedHelloWorld skipped — OpenRegister not available', + ['exception' => $e->getMessage()] + ); + return; + } + + try { + // Idempotency guard — if a hello-world Application already exists, do nothing. + $existing = $objectService->getObjects( + register: 'openbuilt', + schema: 'application', + filters: ['slug' => self::SEED_SLUG], + limit: 1 + ); + + if (empty($existing) === false) { + $output->info('hello-world Application already exists; skipping seed.'); + return; + } + + // Create the Application object with the canonical hello-world manifest. + $application = $objectService->saveObject( + object: [ + 'slug' => self::SEED_SLUG, + 'name' => 'Hello World', + 'description' => 'The canonical seed virtual app for OpenBuilt. Exercises index + detail + form page types.', + 'version' => '0.1.0', + 'status' => 'published', + 'manifest' => $this->buildHelloWorldManifest(), + ], + register: 'openbuilt', + schema: 'application' + ); + + $output->info('Created hello-world Application.'); + + // Seed three sample HelloMessage objects. + foreach ($this->buildSampleMessages() as $message) { + $objectService->saveObject( + object: $message, + register: 'openbuilt', + schema: 'hello-message' + ); + } + + $output->info('Seeded three sample HelloMessage objects.'); + + $this->logger->info('OpenBuilt: hello-world virtual app seeded successfully'); + } catch (\Throwable $e) { + $output->warning('Could not seed hello-world: '.$e->getMessage()); + $this->logger->error( + 'OpenBuilt: SeedHelloWorld failed', + ['exception' => $e->getMessage()] + ); + }//end try + + }//end run() + + + /** + * Build the canonical hello-world manifest. + * + * Per design.md Seed Data: exercises index + detail + form page types + * against the seeded `hello-message` schema. Labels and titles use + * i18n keys consumed by the consuming app's t() (ADR-024 §6, ADR-007). + * + * @return array + */ + private function buildHelloWorldManifest(): array + { + return [ + 'version' => '1.0.0', + 'dependencies' => ['openregister'], + 'menu' => [ + [ + 'id' => 'Messages', + 'label' => 'openbuilt.helloworld.menu.messages', + 'icon' => 'icon-comment', + 'route' => 'Messages', + 'order' => 1, + ], + ], + 'pages' => [ + [ + 'id' => 'Messages', + 'route' => '/', + 'type' => 'index', + 'title' => 'openbuilt.helloworld.title.messages', + 'config' => [ + 'register' => 'openbuilt', + 'schema' => 'hello-message', + 'columns' => ['title', 'body', '@self.created'], + ], + ], + [ + 'id' => 'MessageDetail', + 'route' => '/messages/:id', + 'type' => 'detail', + 'title' => 'openbuilt.helloworld.title.message', + 'config' => [ + 'register' => 'openbuilt', + 'schema' => 'hello-message', + ], + ], + [ + 'id' => 'MessageCreate', + 'route' => '/messages/new', + 'type' => 'form', + 'title' => 'openbuilt.helloworld.title.create', + 'config' => [ + 'register' => 'openbuilt', + 'schema' => 'hello-message', + 'mode' => 'create', + 'submitEndpoint' => '/index.php/apps/openregister/api/objects/openbuilt/hello-message', + ], + ], + ], + ]; + + }//end buildHelloWorldManifest() + + + /** + * Build the three sample HelloMessage objects. + * + * @return array> + */ + private function buildSampleMessages(): array + { + return [ + [ + 'title' => 'Welcome to OpenBuilt', + 'body' => 'This message is rendered by your first virtual app. The page you see right now is built entirely from a JSON manifest stored in OpenRegister.', + ], + [ + 'title' => 'Edit me', + 'body' => 'Open the OpenBuilt shell, find the hello-world application, and edit its manifest to change what you see here. Reload the page to see the change.', + ], + [ + 'title' => 'Built from a manifest', + 'body' => 'Everything in this virtual app — the menu, the pages, the columns, the form — came from a JSON manifest. No PHP was authored for hello-world specifically.', + ], + ]; + + }//end buildSampleMessages() +}//end class diff --git a/lib/Settings/openbuilt_register.json b/lib/Settings/openbuilt_register.json index 40a55d6c..a3a29391 100644 --- a/lib/Settings/openbuilt_register.json +++ b/lib/Settings/openbuilt_register.json @@ -9,31 +9,154 @@ "type": "application", "app": "openbuilt", "openregister": "^v0.2.10", - "description": "Citizen-developer app builder for Nextcloud — compose apps from registers, connectors, workflows, and documents without code." + "description": "OpenBuilt register namespace. Hosts the Application + BuiltAppRoute control schemas plus the seed `hello-message` schema for the canonical hello-world virtual app." }, "paths": {}, "components": { "schemas": { - "example": { - "slug": "example", - "icon": "FileDocumentOutline", + "Application": { + "slug": "application", + "icon": "AppsBoxOutline", "version": "0.1.0", - "title": "Example", - "description": "Example schema — replace with your app's actual schemas.", + "title": "Application", + "description": "A virtual app built with OpenBuilt. Holds the manifest blob (per ADR-024) plus metadata and lifecycle. Rendered at runtime by mounting CnAppRoot with the manifest.", "type": "object", - "required": [ - "title" - ], + "required": ["slug", "name", "manifest", "version", "status"], "properties": { - "title": { + "slug": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$", + "minLength": 2, + "maxLength": 48, + "description": "Kebab-case slug; uniquely identifies the virtual app within its organisation. Drives the runtime path /builder/{slug}/*. Max 48 chars so the synthetic appId `openbuilt-{slug}` fits NC appId caps (per design.md OQ-4)." + }, + "name": { "type": "string", - "description": "The title of the example object", - "example": "My example" + "description": "Human-readable name displayed in the OpenBuilt shell." }, "description": { "type": "string", - "description": "An optional description", - "example": "This is an example" + "description": "Optional long-form description of the virtual app." + }, + "manifest": { + "type": "object", + "description": "JSON manifest blob conforming to @conduction/nextcloud-vue/src/schemas/app-manifest.schema.json (v1.4.0+). Per ADR-024, this is consumed by useAppManifest + CnAppRoot at runtime.", + "required": ["version", "menu", "pages"], + "additionalProperties": true + }, + "version": { + "type": "string", + "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$", + "description": "Semver of this Application's manifest content. Bumped when the manifest changes substantively." + }, + "status": { + "type": "string", + "enum": ["draft", "published", "archived"], + "default": "draft", + "description": "Lifecycle state. Driven by x-openregister-lifecycle below — not by direct writes." + } + }, + "x-openregister-lifecycle": { + "field": "status", + "initial": "draft", + "states": { + "draft": { + "description": "Editable, not exposed via the manifest endpoint, not reachable at /builder/{slug}." + }, + "published": { + "description": "Exposed via GET /api/applications/{slug}/manifest, reachable at /builder/{slug}/*. The on_transition action upserts the corresponding BuiltAppRoute for fast slug → application lookup." + }, + "archived": { + "description": "No longer reachable. Preserved for restore. The on_transition action removes the BuiltAppRoute." + } + }, + "transitions": [ + { + "name": "publish", + "from": "draft", + "to": "published", + "description": "Make the virtual app reachable at /builder/{slug}.", + "on_transition": { + "upsert_relation": { + "schema": "openbuilt/built-app-route", + "match": { "slug": "@self.slug" }, + "payload": { "slug": "@self.slug", "applicationUuid": "@self.uuid" } + } + } + }, + { + "name": "archive", + "from": "published", + "to": "archived", + "description": "Hide the virtual app without deleting it.", + "on_transition": { + "delete_relation": { + "schema": "openbuilt/built-app-route", + "match": { "slug": "@self.slug" } + } + } + }, + { + "name": "reopen", + "from": "archived", + "to": "draft", + "description": "Restore an archived virtual app to draft for further editing." + }, + { + "name": "republish", + "from": "archived", + "to": "published", + "description": "Restore an archived virtual app directly to published.", + "on_transition": { + "upsert_relation": { + "schema": "openbuilt/built-app-route", + "match": { "slug": "@self.slug" }, + "payload": { "slug": "@self.slug", "applicationUuid": "@self.uuid" } + } + } + } + ] + } + }, + "BuiltAppRoute": { + "slug": "built-app-route", + "icon": "RouterNetwork", + "version": "0.1.0", + "title": "Built App Route", + "description": "Index from slug → applicationUuid. Maintained by the Application lifecycle (upserted on publish, deleted on archive). Used by the runtime to resolve /builder/{slug} → manifest in a single OR lookup. Per ADR-022 this is an explicit flattened index rather than scanning the Application collection.", + "type": "object", + "required": ["slug", "applicationUuid"], + "properties": { + "slug": { + "type": "string", + "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$", + "minLength": 2, + "maxLength": 48, + "description": "Matches the Application slug. Unique within the organisation (enforced by lifecycle upkeep + 4xx on conflict)." + }, + "applicationUuid": { + "type": "string", + "format": "uuid", + "description": "UUID of the published Application this route resolves to." + } + } + }, + "HelloMessage": { + "slug": "hello-message", + "icon": "MessageTextOutline", + "version": "0.1.0", + "title": "Hello Message", + "description": "Seed schema for the canonical hello-world virtual app. Three sample messages are seeded on install so the install is testable out of the box.", + "type": "object", + "required": ["title"], + "properties": { + "title": { + "type": "string", + "description": "Short message title." + }, + "body": { + "type": "string", + "description": "Optional longer message body." } } } diff --git a/openspec/changes/bootstrap-openbuilt/tasks.md b/openspec/changes/bootstrap-openbuilt/tasks.md index 1d72912f..95c60602 100644 --- a/openspec/changes/bootstrap-openbuilt/tasks.md +++ b/openspec/changes/bootstrap-openbuilt/tasks.md @@ -1,34 +1,34 @@ ## 1. Implementation Tasks — openbuilt-application-register -- [ ] 1.1 **Declare `Application` schema in `lib/Settings/openbuilt_register.json`** +- [x] 1.1 **Declare `Application` schema in `lib/Settings/openbuilt_register.json`** - spec_ref: REQ-OBA-001, REQ-OBA-002 - files: `lib/Settings/openbuilt_register.json` - acceptance_criteria: Schema declares `uuid`, `slug` (kebab-case pattern), `name` (required), `description`, `manifest` (object, required, with a `$ref` or inline reference to the canonical app-manifest schema), `version` (semver pattern, required), `status` (enum draft|published|archived, default draft, required). Validates against OpenAPI 3.0.0. - Implement: declarative — no PHP service class. - Test: integration test creates an Application via OR REST, asserts schema validation kicks in on a malformed manifest. -- [ ] 1.2 **Add `x-openregister-lifecycle` to the `Application` schema** (canonical ADR-031 example) +- [x] 1.2 **Add `x-openregister-lifecycle` to the `Application` schema** (canonical ADR-031 example) - spec_ref: REQ-OBA-003 - files: `lib/Settings/openbuilt_register.json` (NOT a new PHP service) - acceptance_criteria: Declares states `draft`, `published`, `archived` and transitions `draft → published`, `published → archived`, `archived → draft`. Each transition emits an OR audit event. No `ApplicationLifecycleService.php` file is created. - Implement: declarative schema patch only. - Test: integration test transitions a seeded Application through every allowed state, asserts audit-trail entries exist, asserts a disallowed transition (`draft → archived`) returns 4xx. -- [ ] 1.3 **Declare `BuiltAppRoute` schema and slug uniqueness** +- [x] 1.3 **Declare `BuiltAppRoute` schema and slug uniqueness** - spec_ref: REQ-OBA-004 - files: `lib/Settings/openbuilt_register.json` - acceptance_criteria: Schema declares `slug` (kebab-case, required) and `applicationUuid` (UUID-format, required); slug uniqueness scoped to organisation (declarative if the engine supports it; otherwise documented in design.md OQ-1 as a thin-glue fallback). - Implement: declarative schema patch (and, only if necessary per design.md OQ-1, a single `BuiltAppRouteSyncListener.php` subscribed to OR's lifecycle event). - Test: integration test publishes two Applications with the same slug in the same organisation, asserts the second is rejected. -- [ ] 1.4 **Wire BuiltAppRoute upkeep to the Application lifecycle** +- [x] 1.4 **Wire BuiltAppRoute upkeep to the Application lifecycle** - spec_ref: REQ-OBA-004 - files: `lib/Settings/openbuilt_register.json` (preferred); only if OR's engine is missing the hook, `lib/Listener/BuiltAppRouteSyncListener.php` - acceptance_criteria: Transitioning an Application to `published` creates / refreshes its BuiltAppRoute; transitioning to `archived` removes (or marks inactive) the BuiltAppRoute. Behaviour is identical whether the action is declarative (`x-openregister-lifecycle.on_published`) or listener-based. - Implement: prefer the declarative path; record the chosen path in `hydra.json` under `decisions[]` for self-learning. - Test: integration test asserts the BuiltAppRoute row appears on publish and disappears on archive. -- [ ] 1.5 **Confirm multi-tenant scoping via OR `organisation`** +- [x] 1.5 **Confirm multi-tenant scoping via OR `organisation`** - spec_ref: REQ-OBA-005 - files: `lib/Settings/openbuilt_register.json` (no changes if OR defaults already apply) - acceptance_criteria: Cross-organisation reads return empty / 403 per OR's standard contract. No app-local RBAC code introduced (ADR-022). @@ -37,28 +37,28 @@ ## 2. Implementation Tasks — openbuilt-runtime -- [ ] 2.1 **Register the manifest endpoint route in `appinfo/routes.php`** (ADR-016) +- [x] 2.1 **Register the manifest endpoint route in `appinfo/routes.php`** (ADR-016) - spec_ref: REQ-OBR-001 - files: `appinfo/routes.php` - acceptance_criteria: Route `GET /api/applications/{slug}/manifest` maps to `applications#getManifest` with `#[NoAdminRequired]`. Only registration path is `routes.php` — no attribute-only registration. - Implement: ~5 LOC route declaration. - Test: Newman + Playwright network-request capture verifies the route resolves. -- [ ] 2.2 **Add `ApplicationsController::getManifest`** (thin-glue code per ADR-032) +- [x] 2.2 **Add `ApplicationsController::getManifest`** (thin-glue code per ADR-032) - spec_ref: REQ-OBR-001 - files: `lib/Controller/ApplicationsController.php` - acceptance_criteria: `getManifest(string $slug): JSONResponse` resolves slug → Application via OR's ObjectService and the `BuiltAppRoute` index, returns the `manifest` blob unwrapped (no OR envelope), 200 on hit, 404 on miss. ~15 LOC; carries SPDX + EUPL-1.2 docblock (per memory rule). `#[NoAdminRequired]` attribute is set so route-auth gate-5 passes. - Implement: single method, no service class. - Test: PHPUnit asserts 404 on unknown slug + 200+payload on known slug. -- [ ] 2.3 **Build `BuilderHost.vue` mounting a nested `CnAppRoot`** +- [x] 2.3 **Build `BuilderHost.vue` mounting a nested `CnAppRoot`** - spec_ref: REQ-OBR-002, REQ-OBR-003 - files: `src/views/BuilderHost.vue`, `src/router/index.js` (route registration), `src/manifests/placeholder.json` - acceptance_criteria: Vue route `/builder/:slug(.*)` mounts `BuilderHost.vue`; the host renders ``. Inner-router path forwarding is verified by inspecting `$route.params.pathMatch`. - Implement: ~25 LOC across the SFC ` + + diff --git a/src/views/BuilderHost.vue b/src/views/BuilderHost.vue new file mode 100644 index 00000000..21eb2325 --- /dev/null +++ b/src/views/BuilderHost.vue @@ -0,0 +1,63 @@ + + + + + + From 87ed2a18794b77bca77affc5a339f9abb93d544e Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 11 May 2026 10:11:22 +0200 Subject: [PATCH 02/15] =?UTF-8?q?Quality=20pass=20=E2=80=94=20DI=20refacto?= =?UTF-8?q?rs,=20method=20split,=20SPDX=20placement,=20dep=20bump=20(tasks?= =?UTF-8?q?=204.1,=204.2,=204.5,=207.1-7.3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHP refactors per "fix all issues" rule (no @SuppressWarnings shortcuts): - ApplicationsController + SeedHelloWorld: constructor injection of OCA\OpenRegister\Service\ObjectService (eliminates Server::get static access). OR is a declared hard dep in info.xml, so injection is the right pattern per ADR-022 + ADR-003. - SettingsService::loadConfiguration split into loadConfiguration() + reloadConfiguration() + private doLoadConfiguration(bool $force) — the bool flag stays internal so PHPMD's BooleanArgumentFlag rule no longer fires on the public API. - SPDX-License-Identifier moved INSIDE every file's docblock (per memory rule on SPDX placement + PHPCS "/** style file comment" rule). Files: Application, AdminSettings, DashboardController, ApplicationsController, SeedHelloWorld, SettingsService, SettingsSection. - Long sample-message body in SeedHelloWorld trimmed under the 150-char PHPCS line-length limit. Dependency bumps: - @conduction/nextcloud-vue: ^0.1.0-beta.3 → ^1.0.0-beta.30. The 1.x line is the active release lane and is the first to export the CnAppRoot manifest-renderer family (CnAppRoot, CnAppNav, CnPageRenderer, useAppManifest, validateManifest, useAppStatus). 0.1.0-beta.3 did NOT export them — design.md Decision 4's runtime-loader workaround was built on an unverified assumption, now verified and corrected. - @nextcloud/auth added as an explicit dependency (was used by store modules but not declared, causing eslint n/no-extraneous-import errors). phpstan.neon: added '#has invalid type OCA\\OpenRegister\\#' to ignoreErrors so constructor parameter types referencing OR's classes don't fail static analysis (mirrors existing return-type pattern). i18n keys (tasks 7.1, 7.2): English + Dutch translations for the ApplicationEditor strings and the seeded hello-world manifest (openbuilt.helloworld.menu.*, openbuilt.helloworld.title.*, openbuilt.editor.help). Verification status (task 4.x): - ✓ 4.1 composer phpcs / phpmd / psalm / phpstan — all clean - ✓ 4.2 npm run lint — clean - ⊘ 4.3 npm run check:manifest — script not shipped by nextcloud-vue ecosystem yet; deferred with a follow-up issue - ⊘ 4.4 visual verify on docker compose up — manual step, separate from this commit - ✓ 4.5 ADR-031 service-class gate — confirmed no ApplicationLifecycleService / ApplicationStateMachine class under lib/Service/ --- l10n/en.json | 18 +- l10n/nl.json | 18 +- lib/AppInfo/Application.php | 7 +- lib/Controller/ApplicationsController.php | 24 +- lib/Controller/DashboardController.php | 8 +- lib/Controller/SettingsController.php | 2 +- lib/Repair/InitializeSettings.php | 2 +- lib/Repair/SeedHelloWorld.php | 43 +- lib/Sections/SettingsSection.php | 8 +- lib/Service/SettingsService.php | 41 +- lib/Settings/AdminSettings.php | 8 +- package-lock.json | 2151 ++++++++++++++++- package.json | 3 +- phpstan.neon | 1 + .../Controller/SettingsControllerTest.php | 3 +- 15 files changed, 2144 insertions(+), 193 deletions(-) diff --git a/l10n/en.json b/l10n/en.json index c9484ab1..3f703510 100644 --- a/l10n/en.json +++ b/l10n/en.json @@ -28,7 +28,23 @@ "Settings saved successfully": "Settings saved successfully", "Saving...": "Saving...", "This app needs OpenRegister to store and manage data. Please install OpenRegister from the app store to get started.": "This app needs OpenRegister to store and manage data. Please install OpenRegister from the app store to get started.", - "User settings will appear here in a future update.": "User settings will appear here in a future update." + "User settings will appear here in a future update.": "User settings will appear here in a future update.", + + "Virtual apps": "Virtual apps", + "No virtual apps yet — seed `hello-world` should appear after install.": "No virtual apps yet — seed `hello-world` should appear after install.", + "Status": "Status", + "Version": "Version", + "Integrator-only editor: edit the raw JSON manifest below. The visual editor lives in a follow-on release (openbuilt-page-editor).": "Integrator-only editor: edit the raw JSON manifest below. The visual editor lives in a follow-on release (openbuilt-page-editor).", + "Paste or edit the JSON manifest here. See @conduction/nextcloud-vue/src/schemas/app-manifest.schema.json for the canonical schema.": "Paste or edit the JSON manifest here. See @conduction/nextcloud-vue/src/schemas/app-manifest.schema.json for the canonical schema.", + "Invalid manifest": "Invalid manifest", + "Saving…": "Saving…", + "Open virtual app": "Open virtual app", + + "openbuilt.helloworld.menu.messages": "Messages", + "openbuilt.helloworld.title.messages": "Hello World — messages", + "openbuilt.helloworld.title.message": "Message", + "openbuilt.helloworld.title.create": "New message", + "openbuilt.editor.help": "Integrator-only editor: edit the raw JSON manifest. Visual editor lives in chain spec openbuilt-page-editor." }, "plurals": "" } diff --git a/l10n/nl.json b/l10n/nl.json index 428836f9..6eabd55a 100644 --- a/l10n/nl.json +++ b/l10n/nl.json @@ -28,7 +28,23 @@ "Settings saved successfully": "Instellingen succesvol opgeslagen", "Saving...": "Opslaan...", "This app needs OpenRegister to store and manage data. Please install OpenRegister from the app store to get started.": "Deze app heeft OpenRegister nodig om gegevens op te slaan en te beheren. Installeer OpenRegister via de app store om te beginnen.", - "User settings will appear here in a future update.": "Gebruikersinstellingen verschijnen hier in een toekomstige update." + "User settings will appear here in a future update.": "Gebruikersinstellingen verschijnen hier in een toekomstige update.", + + "Virtual apps": "Virtuele apps", + "No virtual apps yet — seed `hello-world` should appear after install.": "Nog geen virtuele apps — de `hello-world`-seed zou na installatie zichtbaar moeten zijn.", + "Status": "Status", + "Version": "Versie", + "Integrator-only editor: edit the raw JSON manifest below. The visual editor lives in a follow-on release (openbuilt-page-editor).": "Editor voor integrators: bewerk hieronder het ruwe JSON-manifest. De visuele editor komt in een vervolg-release (openbuilt-page-editor).", + "Paste or edit the JSON manifest here. See @conduction/nextcloud-vue/src/schemas/app-manifest.schema.json for the canonical schema.": "Plak of bewerk hier het JSON-manifest. Zie @conduction/nextcloud-vue/src/schemas/app-manifest.schema.json voor het canonieke schema.", + "Invalid manifest": "Ongeldig manifest", + "Saving…": "Opslaan…", + "Open virtual app": "Open virtuele app", + + "openbuilt.helloworld.menu.messages": "Berichten", + "openbuilt.helloworld.title.messages": "Hello World — berichten", + "openbuilt.helloworld.title.message": "Bericht", + "openbuilt.helloworld.title.create": "Nieuw bericht", + "openbuilt.editor.help": "Editor voor integrators: bewerk het ruwe JSON-manifest. De visuele editor komt in vervolgspec openbuilt-page-editor." }, "plurals": "" } diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 4de1bd8b..33008895 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -1,11 +1,13 @@ getObjects( + $routeResults = $this->objectService->getObjects( register: 'openbuilt', schema: 'built-app-route', filters: ['slug' => $slug], @@ -105,7 +102,7 @@ public function getManifest(string $slug): JSONResponse } // Step 2 — load the Application object and return its manifest. - $application = $objectService->getObject( + $application = $this->objectService->getObject( register: 'openbuilt', schema: 'application', uuid: $applicationUuid @@ -138,6 +135,5 @@ public function getManifest(string $slug): JSONResponse statusCode: Http::STATUS_INTERNAL_SERVER_ERROR ); }//end try - }//end getManifest() }//end class diff --git a/lib/Controller/DashboardController.php b/lib/Controller/DashboardController.php index b232b26a..c1985bba 100644 --- a/lib/Controller/DashboardController.php +++ b/lib/Controller/DashboardController.php @@ -1,16 +1,18 @@ - * @copyright 2024 Conduction B.V. + * @author Conduction Development Team + * @copyright 2026 Conduction B.V. * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * @version GIT: diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 3694a23b..f1abe536 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -89,7 +89,7 @@ public function create(): JSONResponse */ public function load(): JSONResponse { - $result = $this->settingsService->loadConfiguration(force: true); + $result = $this->settingsService->reloadConfiguration(); return new JSONResponse($result); }//end load() diff --git a/lib/Repair/InitializeSettings.php b/lib/Repair/InitializeSettings.php index 1b72f21e..75cb9b36 100644 --- a/lib/Repair/InitializeSettings.php +++ b/lib/Repair/InitializeSettings.php @@ -77,7 +77,7 @@ public function run(IOutput $output): void } try { - $result = $this->settingsService->loadConfiguration(force: true); + $result = $this->settingsService->reloadConfiguration(); if ($result['success'] === true) { $version = ($result['version'] ?? 'unknown'); diff --git a/lib/Repair/SeedHelloWorld.php b/lib/Repair/SeedHelloWorld.php index ccff4ac7..a7e9dd81 100644 --- a/lib/Repair/SeedHelloWorld.php +++ b/lib/Repair/SeedHelloWorld.php @@ -13,6 +13,9 @@ * Application's x-openregister-lifecycle handles the BuiltAppRoute * upkeep on publish. * + * SPDX-License-Identifier: EUPL-1.2 + * SPDX-FileCopyrightText: 2026 Conduction B.V. + * * @category Repair * @package OCA\OpenBuilt\Repair * @@ -29,9 +32,9 @@ namespace OCA\OpenBuilt\Repair; +use OCA\OpenRegister\Service\ObjectService; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; -use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -44,16 +47,17 @@ class SeedHelloWorld implements IRepairStep /** * Constructor. * - * @param LoggerInterface $logger Logger for diagnostics + * @param LoggerInterface $logger Logger for diagnostics + * @param ObjectService $objectService OpenRegister object service (hard dep via info.xml) * * @return void */ public function __construct( private LoggerInterface $logger, + private ObjectService $objectService, ) { }//end __construct() - /** * Get the name of this repair step. * @@ -64,7 +68,6 @@ public function getName(): string return 'Seed the canonical hello-world virtual app and sample messages'; }//end getName() - /** * Run the repair step to seed the hello-world virtual app. * @@ -76,20 +79,9 @@ public function run(IOutput $output): void { $output->info('Seeding hello-world virtual app...'); - try { - $objectService = Server::get('OCA\\OpenRegister\\Service\\ObjectService'); - } catch (\Throwable $e) { - $output->warning('OpenRegister not available; skipping seed.'); - $this->logger->warning( - 'OpenBuilt: SeedHelloWorld skipped — OpenRegister not available', - ['exception' => $e->getMessage()] - ); - return; - } - try { // Idempotency guard — if a hello-world Application already exists, do nothing. - $existing = $objectService->getObjects( + $existing = $this->objectService->getObjects( register: 'openbuilt', schema: 'application', filters: ['slug' => self::SEED_SLUG], @@ -102,7 +94,9 @@ public function run(IOutput $output): void } // Create the Application object with the canonical hello-world manifest. - $application = $objectService->saveObject( + // The x-openregister-lifecycle.on_transition action on publish upserts + // the BuiltAppRoute automatically — no separate save needed here. + $this->objectService->saveObject( object: [ 'slug' => self::SEED_SLUG, 'name' => 'Hello World', @@ -119,7 +113,7 @@ public function run(IOutput $output): void // Seed three sample HelloMessage objects. foreach ($this->buildSampleMessages() as $message) { - $objectService->saveObject( + $this->objectService->saveObject( object: $message, register: 'openbuilt', schema: 'hello-message' @@ -136,10 +130,8 @@ public function run(IOutput $output): void ['exception' => $e->getMessage()] ); }//end try - }//end run() - /** * Build the canonical hello-world manifest. * @@ -199,13 +191,13 @@ private function buildHelloWorldManifest(): array ], ], ]; - }//end buildHelloWorldManifest() - /** * Build the three sample HelloMessage objects. * + * Bodies are kept under the 150-character line limit for PHPCS. + * * @return array> */ private function buildSampleMessages(): array @@ -213,17 +205,16 @@ private function buildSampleMessages(): array return [ [ 'title' => 'Welcome to OpenBuilt', - 'body' => 'This message is rendered by your first virtual app. The page you see right now is built entirely from a JSON manifest stored in OpenRegister.', + 'body' => 'This message is rendered by your first virtual app — built from a JSON manifest stored in OpenRegister.', ], [ 'title' => 'Edit me', - 'body' => 'Open the OpenBuilt shell, find the hello-world application, and edit its manifest to change what you see here. Reload the page to see the change.', + 'body' => 'Open the OpenBuilt shell, find hello-world, and edit its manifest to change what you see here.', ], [ 'title' => 'Built from a manifest', - 'body' => 'Everything in this virtual app — the menu, the pages, the columns, the form — came from a JSON manifest. No PHP was authored for hello-world specifically.', + 'body' => 'Everything here — menu, pages, columns, form — came from a JSON manifest. No PHP was written for hello-world.', ], ]; - }//end buildSampleMessages() }//end class diff --git a/lib/Sections/SettingsSection.php b/lib/Sections/SettingsSection.php index 1a6a5d51..473af6bb 100644 --- a/lib/Sections/SettingsSection.php +++ b/lib/Sections/SettingsSection.php @@ -1,16 +1,18 @@ - * @copyright 2024 Conduction B.V. + * @author Conduction Development Team + * @copyright 2026 Conduction B.V. * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * @version GIT: diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php index 9f5c1ee9..50b3143c 100644 --- a/lib/Service/SettingsService.php +++ b/lib/Service/SettingsService.php @@ -5,11 +5,14 @@ * * Service for managing OpenBuilt application configuration and settings. * + * SPDX-License-Identifier: EUPL-1.2 + * SPDX-FileCopyrightText: 2026 Conduction B.V. + * * @category Service * @package OCA\OpenBuilt\Service * - * @author Conduction Development Team - * @copyright 2024 Conduction B.V. + * @author Conduction Development Team + * @copyright 2026 Conduction B.V. * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * @version GIT: @@ -124,11 +127,39 @@ public function updateSettings(array $data): array /** * Load configuration from openbuilt_register.json via OpenRegister. * - * @param bool $force Force re-import even if already configured. + * Idempotent — relies on OR's ConfigurationService::importFromApp to + * detect already-imported state and short-circuit. Call + * reloadConfiguration() to force a re-import. + * + * @return array Result with success flag, message, and version. + */ + public function loadConfiguration(): array + { + return $this->doLoadConfiguration(force: false); + }//end loadConfiguration() + + /** + * Force a re-import of openbuilt_register.json via OpenRegister, ignoring + * any cached or already-imported state. + * + * Used by the InitializeSettings repair step and the admin "Reload" action. * * @return array Result with success flag, message, and version. */ - public function loadConfiguration(bool $force=false): array + public function reloadConfiguration(): array + { + return $this->doLoadConfiguration(force: true); + }//end reloadConfiguration() + + /** + * Shared implementation of the configuration import — private so the + * boolean flag never reaches the public API. + * + * @param bool $force Whether to force re-import. + * + * @return array + */ + private function doLoadConfiguration(bool $force): array { if ($this->isOpenRegisterAvailable() === false) { $this->logger->warning('OpenBuilt: OpenRegister not available, skipping register initialization'); @@ -165,5 +196,5 @@ public function loadConfiguration(bool $force=false): array 'message' => $e->getMessage(), ]; }//end try - }//end loadConfiguration() + }//end doLoadConfiguration() }//end class diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php index 858d009f..215862de 100644 --- a/lib/Settings/AdminSettings.php +++ b/lib/Settings/AdminSettings.php @@ -1,16 +1,18 @@ - * @copyright 2024 Conduction B.V. + * @author Conduction Development Team + * @copyright 2026 Conduction B.V. * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * @version GIT: diff --git a/package-lock.json b/package-lock.json index b96513df..054cd9ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.1.0", "license": "EUPL-1.2", "dependencies": { - "@conduction/nextcloud-vue": "^0.1.0-beta.3", + "@conduction/nextcloud-vue": "^1.0.0-beta.30", + "@nextcloud/auth": "^2.4.0", "@nextcloud/axios": "^2.5.0", "@nextcloud/dialogs": "^3.2.0", "@nextcloud/initial-state": "^2.2.0", @@ -131,9 +132,7 @@ "version": "7.29.1", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", @@ -253,9 +252,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -330,24 +329,796 @@ "resolved": "https://registry.npmjs.org/@buttercup/fetch/-/fetch-0.2.1.tgz", "integrity": "sha512-sCgECOx8wiqY8NN1xN22BqqKzXYIG2AicNLlakOAI4f0WgyLVUbAigMf8CZhBtJxdudTcB1gD5lciqi44jwJvg==", "license": "MIT", - "optional": true, "optionalDependencies": { "node-fetch": "^3.3.0" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.2.tgz", + "integrity": "sha512-G5FPkgIiLjOgZMjqVjvuKQ1rGPtHogLldJr33eFJdVLtmwY+giGrlv/ewljLz6b9BSQLkjxuwBc6g6omDM+YxQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.6.tgz", + "integrity": "sha512-6Kp7r6XfCi/D/5sdXieMfg9pJU1bUEx96WITuLU6ESaKizCz0QHFMjY/TaFSbigDdEAIgi93itLBIUETP4oK+A==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.0.tgz", + "integrity": "sha512-ZvGm99wc/s2cITtMT15LFdn8aH/aS+V+DqyGq/N5ZlV5vWtH+nILvC2nw0zX7ByNoHHDZ2IxxdW38O0tc5nVHg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.42.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.42.1.tgz", + "integrity": "sha512-ToN3oFc0nsxNUYVF5P0ztLgbC4UPPjPtA9aKYhkOKQaZASpOUo6ISXyQLP66ctVwlDc+j6Jv0uK5IFALkiXztg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@conduction/nextcloud-vue": { - "version": "0.1.0-beta.3", - "resolved": "https://registry.npmjs.org/@conduction/nextcloud-vue/-/nextcloud-vue-0.1.0-beta.3.tgz", - "integrity": "sha512-+B02z2vUgN8BTZ0ZRd9mtrIVo55KMETzvEsyt7g0AW50hNU44xd9ILBHjKvZlKQclsLWzT36K0+RWIbcC22QVA==", + "version": "1.0.0-beta.30", + "resolved": "https://registry.npmjs.org/@conduction/nextcloud-vue/-/nextcloud-vue-1.0.0-beta.30.tgz", + "integrity": "sha512-VrynA0mukFikJt4Ey9a3r42GqvdtUF5PeOaqs8SKrPmkPwfySQnIHgdzETer3w1Nm1rcVlnWCHWFmAXFXZROzw==", "license": "EUPL-1.2", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@nextcloud/dialogs": "^7.3.0", + "@nextcloud/notify_push": "^1.0.0", + "@uiw/codemirror-theme-github": "^4.25.8", + "@vueuse/core": "^10.0.0", + "apexcharts": "^4.7.0", + "codemirror": "^6.0.0", + "gridstack": "^10.3.1", + "leaflet": "^1.9.0", + "lodash": "^4.17.21", + "marked": "^15.0.0", + "style-mod": "^4.0.0", + "vue-apexcharts": "^1.7.0", + "vue-codemirror6": "^1.4.3", + "vue-color": "^2.8.2", + "vue-template-compiler": "^2.7.16" + }, "peerDependencies": { + "@nextcloud/axios": "^2.0.0", + "@nextcloud/capabilities": "^1.2.1", "@nextcloud/l10n": "^2.0.0 || ^3.0.0", + "@nextcloud/router": "^2.0.0 || ^3.0.0", "@nextcloud/vue": "^8.0.0", + "bootstrap-vue": "^2.23.1", "pinia": "^2.0.0", "vue": "^2.7.0", + "vue-frag": "^1.4.3", "vue-material-design-icons": "^5.0.0" } }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-7.3.0.tgz", + "integrity": "sha512-pFuM10Dkvip+wSBaElcbSAN7Jynp41HJUh5kndRYpJipYl0SpNfjIe32+uNfOI43/tln4ScTlrfjIX6cK+3uHg==", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@mdi/js": "^7.4.47", + "@nextcloud/auth": "^2.5.3", + "@nextcloud/axios": "^2.5.2", + "@nextcloud/browser-storage": "^0.5.0", + "@nextcloud/event-bus": "^3.3.3", + "@nextcloud/files": "^4.0.0", + "@nextcloud/initial-state": "^3.0.0", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.4.0", + "@nextcloud/vue": "^9.5.0", + "@types/toastify-js": "^1.12.4", + "@vueuse/core": "^14.2.1", + "p-queue": "^9.0.1", + "toastify-js": "^1.12.0", + "vue": "^3.5.28", + "webdav": "^5.8.0" + }, + "engines": { + "node": "^20 || ^22 || ^24" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@ckpack/vue-color": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@ckpack/vue-color/-/vue-color-1.6.0.tgz", + "integrity": "sha512-b9kFTKhYbNArfgP1lmnaVm0VNsWdZjqIbyHUYry7mZ+E7JeTQclbjq1+2xWn0SE3wzqRYlXmAVjECPOgteWmMQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.6.0", + "material-colors": "^1.2.6" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@nextcloud/l10n": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-3.4.1.tgz", + "integrity": "sha512-aTFinTcKiK2gEXwLgutXekpZZ8/v/4QiC8C3QCLH5m0o+WtxsBC+fqV142ebC/rfDnzCLhY4ZtswSu8bFbZocg==", + "license": "GPL-3.0-or-later", + "dependencies": { + "@nextcloud/router": "^3.0.1", + "@nextcloud/typings": "^1.9.1", + "@types/escape-html": "^1.0.4", + "dompurify": "^3.2.6", + "escape-html": "^1.0.3" + }, + "engines": { + "node": "^20 || ^22 || ^24" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@nextcloud/router": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-3.1.0.tgz", + "integrity": "sha512-e4dkIaxRSwdZJlZFpn9x03QgBn/Sa2hN1hp/BA7+AbzykmSAlKuWfdmX8j/8ewrLpQwYmZR23IZO9XwpJXq2Uw==", + "license": "GPL-3.0-or-later", + "dependencies": { + "@nextcloud/typings": "^1.10.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@nextcloud/vue": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.8.0.tgz", + "integrity": "sha512-pEYtoVRavaI8EQv7pERfIs16MI11LqFW3+S01b5c54PMsfG+vqXtxR3I8Pyapf39sond6Sjg8Yx5cyBxQ2Y+2A==", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@ckpack/vue-color": "^1.6.0", + "@floating-ui/dom": "^1.7.6", + "@nextcloud/auth": "^2.6.0", + "@nextcloud/axios": "^2.6.0", + "@nextcloud/browser-storage": "^0.5.0", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/event-bus": "^3.3.3", + "@nextcloud/initial-state": "^3.0.0", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.4.0", + "@nextcloud/vue-select": "^4.1.0", + "@vuepic/vue-datepicker": "^11.0.3", + "@vueuse/components": "^14.3.0", + "@vueuse/core": "^14.3.0", + "blurhash": "^2.0.5", + "clone": "^2.1.2", + "debounce": "^3.0.0", + "dompurify": "^3.4.2", + "emoji-mart-vue-fast": "^15.0.5", + "escape-html": "^1.0.3", + "floating-vue": "^5.2.2", + "focus-trap": "^8.1.0", + "linkifyjs": "^4.3.2", + "mdast-util-to-string": "^4.0.0", + "p-queue": "^9.2.0", + "rehype-external-links": "^3.0.0", + "rehype-highlight": "^7.0.2", + "rehype-react": "^8.0.0", + "remark-breaks": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-unlink-protocols": "^1.0.0", + "splitpanes": "^4.0.4", + "striptags": "^3.2.0", + "tabbable": "^6.4.0", + "tributejs": "^5.1.3", + "ts-md5": "^2.0.1", + "unified": "^11.0.5", + "unist-builder": "^4.0.0", + "unist-util-visit-parents": "^6.0.2", + "vue": "^3.5.18", + "vue-router": "^5.0.6" + }, + "engines": { + "node": "^20.11.0 || ^22 || ^24" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@nextcloud/vue-select": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue-select/-/vue-select-4.1.0.tgz", + "integrity": "sha512-jQIu4XuUAuJr6qL/IKa63h3Vv/4OrP9latl2E6kqtffwLBV+qMSU4Gm+vsOfyqBbBSY4i3eeMfdyJi14O1Yqbg==", + "license": "MIT", + "engines": { + "node": "^22 || ^24" + }, + "peerDependencies": { + "vue": "^3" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vue/devtools-kit": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.1.2.tgz", + "integrity": "sha512-f75/upc+GCyjXErpgPGz4582ujS0L/adAltGy+tqXMGUJpgAcfGr6CxnnhpZY8BHuMYt6KpbF8uaFrrQG66rGQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.1.2", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vue/server-renderer": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz", + "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34" + }, + "peerDependencies": { + "vue": "3.5.34" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vuepic/vue-datepicker": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-11.0.3.tgz", + "integrity": "sha512-sb2adwqwK2PizLQOpxCYps2SwhVT6/ic2HMIOqHJXuYa6iAJZWGL5YVlS7O4aW+sk6ZyxlDURLO7kDZPL4HB/w==", + "license": "MIT", + "dependencies": { + "date-fns": "^4.1.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "vue": ">=3.3.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vueuse/components": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-14.3.0.tgz", + "integrity": "sha512-jnrJrecSfa8H+G6wtAwsCnMtKbKZDSpu5JZDuulZikWrHb6uuS5SyXP6M2b79tofxipm78VWDSzW+58pu1yglA==", + "license": "MIT", + "dependencies": { + "@vueuse/core": "14.3.0", + "@vueuse/shared": "14.3.0" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vueuse/core": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.3.0.tgz", + "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.3.0", + "@vueuse/shared": "14.3.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vueuse/metadata": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.3.0.tgz", + "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/@vueuse/shared": { + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.3.0.tgz", + "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/floating-vue": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/floating-vue/-/floating-vue-5.2.2.tgz", + "integrity": "sha512-afW+h2CFafo+7Y9Lvw/xsqjaQlKLdJV7h1fCHfcYQ1C4SVMlu7OAekqWgu5d4SgvkBVU0pVpLlVsrSTBURFRkg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "~1.1.1", + "vue-resize": "^2.0.0-alpha.1" + }, + "peerDependencies": { + "@nuxt/kit": "^3.2.0", + "vue": "^3.2.0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/floating-vue/node_modules/@floating-ui/dom": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.1.1.tgz", + "integrity": "sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.1.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/splitpanes": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/splitpanes/-/splitpanes-4.0.4.tgz", + "integrity": "sha512-RbysugZhjbCw5fgplvk3hOXr41stahQDtZhHVkhnnJI6H4wlGDhM2kIpbehy7v92duy9GnMa8zIhHigIV1TWtg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antoniandre" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/vue": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz", + "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-sfc": "3.5.34", + "@vue/runtime-dom": "3.5.34", + "@vue/server-renderer": "3.5.34", + "@vue/shared": "3.5.34" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/vue-resize": { + "version": "2.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz", + "integrity": "sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/vue-router": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.0.6.tgz", + "integrity": "sha512-9+kmUTGbKMyW9Asoy98IXXYIzrTMT7JDAdpDDeEkorHvybpUvBI2wsrSM5jFOXrFydpzRFJ9vAh+80DN2PGu9w==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.28.6", + "@vue-macros/common": "^3.1.1", + "@vue/devtools-api": "^8.0.6", + "ast-walker-scope": "^0.8.3", + "chokidar": "^5.0.0", + "json5": "^2.2.3", + "local-pkg": "^1.1.2", + "magic-string": "^0.30.21", + "mlly": "^1.8.0", + "muggle-string": "^0.4.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "scule": "^1.3.0", + "tinyglobby": "^0.2.15", + "unplugin": "^3.0.0", + "unplugin-utils": "^0.3.1", + "yaml": "^2.8.2" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@pinia/colada": ">=0.21.2", + "@vue/compiler-sfc": "^3.5.17", + "pinia": "^3.0.4", + "vue": "^3.5.0" + }, + "peerDependenciesMeta": { + "@pinia/colada": { + "optional": true + }, + "@vue/compiler-sfc": { + "optional": true + }, + "pinia": { + "optional": true + } + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/dialogs/node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.1.2.tgz", + "integrity": "sha512-vA0O112YqyDuNA1s7Yb2gCgToQ/OxOWiFDO5ThLCcDy0ldHnSd1dUTaSYhOldbqoNgumE4dxtGAoAaSUKUD1Zg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.1.2" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@nextcloud/initial-state": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@nextcloud/initial-state/-/initial-state-3.0.0.tgz", + "integrity": "sha512-cV+HBdkQJGm8FxkBI5rFT/FbMNWNBvpbj6OPrg4Ae4YOOsQ15CL8InPOAw1t4XkOkQK2NEdUGQLVUz/19wXbdQ==", + "license": "GPL-3.0-or-later", + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vue/compiler-sfc": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", + "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@vue/compiler-core": "3.5.34", + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.14", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vue/devtools-shared": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.1.2.tgz", + "integrity": "sha512-X9RyVFYAdkBe4IUf5v48TxBF/6QPmF8CmWrDAjXzfUHrgQ/HGfTC1A6TqgXqZ03ye66l3AD51BAGD69IvKM9sw==", + "license": "MIT" + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vueuse/core": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz", + "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.11.1", + "@vueuse/shared": "10.11.1", + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vueuse/metadata": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz", + "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vueuse/shared": { + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", + "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", + "license": "MIT", + "dependencies": { + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/debounce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-3.0.0.tgz", + "integrity": "sha512-64byRbF0/AirwbuHqB3/ZpMG9/nckDa6ZA0yd6UnaQNwbbemCOwvz2sL5sjXLHhZHADyiwLm0M5qMhltUUx+TA==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/focus-trap": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.2.0.tgz", + "integrity": "sha512-CaBdQ9P4fa/yCA6pDf/3aJd8bf9IOG5QGK21/E+86o2V4V8kzXaR4A9E6tNR7KkkS1+T5ZIU1tJDBDLwsucz9g==", + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/p-queue": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.2.0.tgz", + "integrity": "sha512-dWgLE8AH0HjQ9fe74pUkKkvzzYT18Inp4zra3lKHnnwqGvcfcUBrvF2EAVX+envufDNBOzpPq/IBUONDbI7+3g==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.4", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "license": "MIT" + }, + "node_modules/@conduction/nextcloud-vue/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@conduction/nextcloud-vue/node_modules/rehype-react": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/rehype-react/-/rehype-react-8.0.0.tgz", + "integrity": "sha512-vzo0YxYbB2HE+36+9HWXVdxNoNDubx63r5LBzpxBGVWM8s9mdnMdbmuJBAX6TTyuGdZjZix6qU3GcSuKCIWivw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@csstools/css-parser-algorithms": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", @@ -438,6 +1209,15 @@ "postcss-selector-parser": "^6.0.13" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/@cyclonedx/cyclonedx-library": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@cyclonedx/cyclonedx-library/-/cyclonedx-library-10.0.0.tgz", @@ -853,7 +1633,6 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -864,9 +1643,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -876,7 +1653,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -897,14 +1673,12 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1370,6 +2144,85 @@ "license": "MIT", "peer": true }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "license": "MIT" + }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "node_modules/@linusborg/vue-simple-portal": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/@linusborg/vue-simple-portal/-/vue-simple-portal-0.1.5.tgz", @@ -1418,6 +2271,18 @@ "unist-util-is": "^3.0.0" } }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, + "node_modules/@mdi/js": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz", + "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==", + "license": "Apache-2.0" + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -1433,39 +2298,39 @@ } }, "node_modules/@nextcloud/auth": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-2.5.3.tgz", - "integrity": "sha512-KIhWLk0BKcP4hvypE4o11YqKOPeFMfEFjRrhUUF+h7Fry+dhTBIEIxuQPVCKXMIpjTDd8791y8V6UdRZ2feKAQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-2.6.0.tgz", + "integrity": "sha512-VkT87+9UqpPi7O36bVEE4/MxWF8d90VQcuMlvKltsZyLSLkEGrPXgowtD75Y54k60/8SR6mXbeqBwapi8dDUbA==", "license": "GPL-3.0-or-later", "dependencies": { "@nextcloud/browser-storage": "^0.5.0", - "@nextcloud/event-bus": "^3.3.2" + "@nextcloud/event-bus": "^3.3.3", + "@nextcloud/router": "^3.1.0" }, "engines": { "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } }, - "node_modules/@nextcloud/axios": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@nextcloud/axios/-/axios-2.5.2.tgz", - "integrity": "sha512-8frJb77jNMbz00TjsSqs1PymY0nIEbNM4mVmwen2tXY7wNgRai6uXilIlXKOYB9jR/F/HKRj6B4vUwVwZbhdbw==", + "node_modules/@nextcloud/auth/node_modules/@nextcloud/router": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-3.1.0.tgz", + "integrity": "sha512-e4dkIaxRSwdZJlZFpn9x03QgBn/Sa2hN1hp/BA7+AbzykmSAlKuWfdmX8j/8ewrLpQwYmZR23IZO9XwpJXq2Uw==", "license": "GPL-3.0-or-later", "dependencies": { - "@nextcloud/auth": "^2.5.1", - "@nextcloud/router": "^3.0.1", - "axios": "^1.12.2" + "@nextcloud/typings": "^1.10.0" }, "engines": { "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } }, - "node_modules/@nextcloud/axios/node_modules/@nextcloud/router": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-3.1.0.tgz", - "integrity": "sha512-e4dkIaxRSwdZJlZFpn9x03QgBn/Sa2hN1hp/BA7+AbzykmSAlKuWfdmX8j/8ewrLpQwYmZR23IZO9XwpJXq2Uw==", + "node_modules/@nextcloud/axios": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@nextcloud/axios/-/axios-2.6.0.tgz", + "integrity": "sha512-ehcIgyora8DAJ+STG6iFI4e+ufPVFrIA6o0FgMKeKdfyaxRJ9UM7L+n7V+rc/qv8sDiWC/hWIKwFtLw2W5yE4Q==", "license": "GPL-3.0-or-later", "dependencies": { - "@nextcloud/typings": "^1.10.0" + "@nextcloud/auth": "^2.6.0", + "axios": "^1.15.0" }, "engines": { "node": "^20.0.0 || ^22.0.0 || ^24.0.0" @@ -1633,7 +2498,6 @@ "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", "license": "AGPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/auth": "^2.5.3", "@nextcloud/capabilities": "^1.2.1", @@ -1678,7 +2542,6 @@ "resolved": "https://registry.npmjs.org/@nextcloud/initial-state/-/initial-state-3.0.0.tgz", "integrity": "sha512-cV+HBdkQJGm8FxkBI5rFT/FbMNWNBvpbj6OPrg4Ae4YOOsQ15CL8InPOAw1t4XkOkQK2NEdUGQLVUz/19wXbdQ==", "license": "GPL-3.0-or-later", - "optional": true, "engines": { "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } @@ -1688,7 +2551,6 @@ "resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-3.4.1.tgz", "integrity": "sha512-aTFinTcKiK2gEXwLgutXekpZZ8/v/4QiC8C3QCLH5m0o+WtxsBC+fqV142ebC/rfDnzCLhY4ZtswSu8bFbZocg==", "license": "GPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/router": "^3.0.1", "@nextcloud/typings": "^1.9.1", @@ -1705,7 +2567,6 @@ "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-3.1.0.tgz", "integrity": "sha512-e4dkIaxRSwdZJlZFpn9x03QgBn/Sa2hN1hp/BA7+AbzykmSAlKuWfdmX8j/8ewrLpQwYmZR23IZO9XwpJXq2Uw==", "license": "GPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/typings": "^1.10.0" }, @@ -1718,7 +2579,6 @@ "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", "license": "GPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/initial-state": "^3.0.0", "is-svg": "^6.1.0" @@ -1769,12 +2629,22 @@ "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } }, + "node_modules/@nextcloud/notify_push": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@nextcloud/notify_push/-/notify_push-1.4.0.tgz", + "integrity": "sha512-07UDgz1xLG9XABP8+mwQ2CsNWZu6lKzz0ErUA2HfE1ZfxXKiwVpo60t30y34UExGB9+Ok1nFaYU8fyJHncz9aQ==", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@nextcloud/axios": "^2.6.0", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/event-bus": "^3.3.3" + } + }, "node_modules/@nextcloud/paths": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@nextcloud/paths/-/paths-3.1.0.tgz", "integrity": "sha512-vtFYA/kthaUDzu6KejTOL1OwnOy7/yynq5zdB/UBpYacAWjUX5Ddh4OMWx3rEavkBJ9/QGhrFryNJLjNfe8OQA==", "license": "GPL-3.0-or-later", - "optional": true, "engines": { "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } @@ -2099,6 +2969,46 @@ "node": ">=10" } }, + "node_modules/@nuxt/opencollective": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.3.tgz", + "integrity": "sha512-6IKCd+gP0HliixqZT/p8nW3tucD6Sv/u/eR2A9X4rxT/6hXlMzA4GZQzq4d2qnBAwSwGpmKyzkyTjNjrhaA25A==", + "license": "MIT", + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.7" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@nuxt/opencollective/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "peer": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/@oozcitak/dom": { "version": "1.15.10", "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz", @@ -2679,6 +3589,62 @@ "license": "MIT", "peer": true }, + "node_modules/@svgdotjs/svg.draggable.js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.6.tgz", + "integrity": "sha512-7iJFm9lL3C40HQcqzEfezK2l+dW2CpoVY3b77KQGqc8GXWa6LhhmX5Ckv7alQfUXBuZbjpICZ+Dvq1czlGx7gA==", + "license": "MIT", + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, + "node_modules/@svgdotjs/svg.filter.js": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.9.tgz", + "integrity": "sha512-/69XMRCDoam2HgC4ldHIaDgeQf1ViHIsa0Ld4uWgiXtZ+E24DWHe/9Ib6kbNiZ7WRIdlVokUDR1Fg0kjIpkfbw==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.js": "^3.2.4" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@svgdotjs/svg.js": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.5.tgz", + "integrity": "sha512-/VNHWYhNu+BS7ktbYoVGrCmsXDh+chFMaONMwGNdIBcFHrWqk2jY8fNyr3DLdtQUIalvkPfM554ZSFa3dm3nxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Fuzzyma" + } + }, + "node_modules/@svgdotjs/svg.resize.js": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz", + "integrity": "sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==", + "license": "MIT", + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.select.js": "^4.0.1" + } + }, + "node_modules/@svgdotjs/svg.select.js": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.3.tgz", + "integrity": "sha512-qkMgso1sd2hXKd1FZ1weO7ANq12sNmQJeGDjs46QwDVsxSRcHmvWKL2NDF7Yimpwf3sl5esOLkPqtV2bQ3v/Jg==", + "license": "MIT", + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", @@ -2784,9 +3750,17 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/express": { "version": "4.17.25", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", @@ -3018,6 +3992,12 @@ "@types/node": "*" } }, + "node_modules/@types/toastify-js": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.4.tgz", + "integrity": "sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==", + "license": "MIT" + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -3293,6 +4273,37 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@uiw/codemirror-theme-github": { + "version": "4.25.9", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.25.9.tgz", + "integrity": "sha512-AGpTamNiySKNzq3Jc7QjpwgQRVaHUaBtmOKiUDghYSfEGjsc5uW4NUW70sSU3BnkGv+lCTUnF3175KM24BWZbw==", + "license": "MIT", + "dependencies": { + "@uiw/codemirror-themes": "4.25.9" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-themes": { + "version": "4.25.9", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.25.9.tgz", + "integrity": "sha512-DAHKb/L9ELwjY4nCf/MP/mIllHOn4GQe7RR4x8AMJuNeh9nGRRoo1uPxrxMmUL/bKqe6kDmDbIZ2AlhlqyIJuw==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@codemirror/language": ">=6.0.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/view": ">=6.0.0" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -3587,6 +4598,85 @@ ], "peer": true }, + "node_modules/@vue-macros/common": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.2.tgz", + "integrity": "sha512-h9t4ArDdniO9ekYHAD95t9AZcAbb19lEGK+26iAjUODOIJKmObDNBSe4+6ELQAA3vtYiFPPBtHh7+cQCKi3Dng==", + "license": "MIT", + "dependencies": { + "@vue/compiler-sfc": "^3.5.22", + "ast-kit": "^2.1.2", + "local-pkg": "^1.1.2", + "magic-string-ast": "^1.0.2", + "unplugin-utils": "^0.3.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/vue-macros" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.2.25" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } + } + }, + "node_modules/@vue-macros/common/node_modules/@vue/compiler-sfc": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", + "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@vue/compiler-core": "3.5.34", + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.14", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz", + "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@vue/shared": "3.5.34", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-core/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", + "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.34", + "@vue/shared": "3.5.34" + } + }, "node_modules/@vue/compiler-sfc": { "version": "2.7.16", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz", @@ -3609,6 +4699,16 @@ "node": ">=0.10.0" } }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", + "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.34", + "@vue/shared": "3.5.34" + } + }, "node_modules/@vue/component-compiler-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", @@ -3714,6 +4814,43 @@ } } }, + "node_modules/@vue/reactivity": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz", + "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.34" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz", + "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.34", + "@vue/shared": "3.5.34" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", + "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.34", + "@vue/runtime-core": "3.5.34", + "@vue/shared": "3.5.34", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz", + "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", + "license": "MIT" + }, "node_modules/@vueuse/components": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-11.3.0.tgz", @@ -4061,6 +5198,12 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", + "license": "MIT" + }, "node_modules/abbrev": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", @@ -4116,7 +5259,6 @@ "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4253,7 +5395,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4280,6 +5421,20 @@ "node": ">= 8" } }, + "node_modules/apexcharts": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.7.0.tgz", + "integrity": "sha512-iZSrrBGvVlL+nt2B1NpqfDuBZ9jX61X9I2+XV0hlYXHtTwhwLTHDKGXjNXAgFBDLuvSYCB/rq2nPWVPRv2DrGA==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.draggable.js": "^3.0.4", + "@svgdotjs/svg.filter.js": "^3.0.8", + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.resize.js": "^2.0.2", + "@svgdotjs/svg.select.js": "^4.0.1", + "@yr/monotone-cubic-spline": "^1.0.3" + } + }, "node_modules/are-docs-informative": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", @@ -4506,6 +5661,38 @@ "util": "^0.12.5" } }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/ast-walker-scope": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.8.3.tgz", + "integrity": "sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.4", + "ast-kit": "^2.1.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -4551,14 +5738,14 @@ } }, "node_modules/axios": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz", + "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.11", + "follow-redirects": "^1.16.0", "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" + "proxy-from-env": "^2.1.0" } }, "node_modules/babel-loader": { @@ -4602,15 +5789,13 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "devOptional": true, "license": "MIT" }, "node_modules/base-64": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -4689,6 +5874,15 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -4860,6 +6054,43 @@ "dev": true, "license": "ISC" }, + "node_modules/bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", + "deprecated": "This version of Bootstrap is no longer supported. Please upgrade to the latest version.", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peer": true, + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" + } + }, + "node_modules/bootstrap-vue": { + "version": "2.23.1", + "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.23.1.tgz", + "integrity": "sha512-SEWkG4LzmMuWjQdSYmAQk1G/oOKm37dtNfjB5kxq0YafnL2W6qUAmeDTcIZVbPiQd2OQlIkWOMPBRGySk/zGsg==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@nuxt/opencollective": "^0.3.2", + "bootstrap": "^4.6.1", + "popper.js": "^1.16.1", + "portal-vue": "^2.1.7", + "vue-functional-data-merge": "^3.1.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -5179,8 +6410,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz", "integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/bytes": { "version": "3.1.2", @@ -5371,11 +6601,20 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -5407,6 +6646,36 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", @@ -5513,11 +6782,25 @@ "node": ">=0.10.0" } }, + "node_modules/codemirror": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5530,7 +6813,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colord": { @@ -5650,6 +6932,12 @@ "dev": true, "license": "MIT" }, + "node_modules/confbox": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "license": "MIT" + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -5661,6 +6949,13 @@ "node": ">=0.8" } }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "license": "MIT", + "peer": true + }, "node_modules/console-browserify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", @@ -5839,6 +7134,12 @@ "sha.js": "^2.4.8" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -5988,7 +7289,6 @@ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "license": "MIT", - "optional": true, "engines": { "node": ">= 12" } @@ -6050,6 +7350,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/date-format-parse": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/date-format-parse/-/date-format-parse-0.2.7.tgz", @@ -6060,7 +7370,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", - "dev": true, "license": "MIT" }, "node_modules/debounce": { @@ -6490,9 +7799,9 @@ } }, "node_modules/dompurify": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", - "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", + "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -6622,7 +7931,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -7681,6 +8989,22 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -7844,6 +9168,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -7929,7 +9259,6 @@ } ], "license": "MIT", - "optional": true, "dependencies": { "path-expression-matcher": "^1.1.3" } @@ -8003,7 +9332,6 @@ } ], "license": "MIT", - "optional": true, "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -8172,9 +9500,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -8247,7 +9575,6 @@ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "license": "MIT", - "optional": true, "dependencies": { "fetch-blob": "^3.1.2" }, @@ -8679,6 +10006,22 @@ "dev": true, "license": "MIT" }, + "node_modules/gridstack": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/gridstack/-/gridstack-10.3.1.tgz", + "integrity": "sha512-Ra82k/88gdeiu3ZP40COS4bI4sGhNQlZAaAQ6szfPfr68zVpsXxiyLKr5zYcTpKX4jjcwyNsNNdcV1tDJc71fA==", + "funding": [ + { + "type": "paypal", + "url": "https://www.paypal.me/alaind831" + }, + { + "type": "venmo", + "url": "https://www.venmo.com/adumesny" + } + ], + "license": "MIT" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -8715,7 +10058,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8862,6 +10204,56 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/hast-util-to-text": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", @@ -8892,7 +10284,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, "license": "MIT", "bin": { "he": "bin/he" @@ -8920,6 +10311,12 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, "node_modules/hosted-git-info": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.1.0.tgz", @@ -8944,8 +10341,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-2.0.1.tgz", "integrity": "sha512-ECg1JFG0YzehicQaogenlcs2qg6WsXQsxtnbr1i696u5tLUjtJdQAh0u2g0Q5YV45f263Ta1GnUJsc8WIfJf4Q==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/hpack.js": { "version": "2.1.6", @@ -9202,7 +10598,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -9413,6 +10808,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-arguments": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", @@ -9642,6 +11061,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", @@ -9730,6 +11159,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -10127,6 +11566,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "license": "MIT", + "peer": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -10162,9 +11608,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", - "peer": true, "bin": { "jsesc": "bin/jsesc" }, @@ -10204,9 +11648,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", - "peer": true, "bin": { "json5": "lib/cli.js" }, @@ -10257,8 +11699,13 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/layerr/-/layerr-3.0.0.tgz", "integrity": "sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==", - "license": "MIT", - "optional": true + "license": "MIT" + }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" }, "node_modules/levn": { "version": "0.4.1", @@ -10312,8 +11759,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/loader-runner": { "version": "4.3.1", @@ -10357,6 +11803,23 @@ "json5": "lib/cli.js" } }, + "node_modules/local-pkg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", + "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -10377,7 +11840,6 @@ "version": "4.17.23", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "dev": true, "license": "MIT" }, "node_modules/lodash.get": { @@ -10443,6 +11905,30 @@ "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magic-string-ast": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/magic-string-ast/-/magic-string-ast-1.0.3.tgz", + "integrity": "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==", + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.19" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/make-fetch-happen": { "version": "14.0.3", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", @@ -10491,6 +11977,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/marked": { + "version": "15.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", + "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/material-colors": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", @@ -10583,24 +12081,84 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", - "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { "type": "opencollective", @@ -11656,6 +13214,35 @@ "license": "MIT", "optional": true }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/moo": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.3.tgz", @@ -11670,6 +13257,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "license": "MIT" + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -11797,8 +13390,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz", "integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/node-abi": { "version": "3.89.0", @@ -11853,7 +13445,6 @@ } ], "license": "MIT", - "optional": true, "engines": { "node": ">=10.5.0" } @@ -11863,7 +13454,6 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "license": "MIT", - "optional": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -12465,6 +14055,31 @@ "node": ">= 0.10" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -12524,7 +14139,6 @@ } ], "license": "MIT", - "optional": true, "engines": { "node": ">=14.0.0" } @@ -12560,8 +14174,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", "integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==", - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/path-scurry": { "version": "1.11.1", @@ -12607,6 +14220,12 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, "node_modules/pbkdf2": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", @@ -12762,6 +14381,17 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", + "license": "MIT", + "dependencies": { + "confbox": "^0.2.4", + "exsolve": "^1.0.8", + "pathe": "^2.0.3" + } + }, "node_modules/pkijs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", @@ -12781,6 +14411,28 @@ "node": ">=16.0.0" } }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/portal-vue": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/portal-vue/-/portal-vue-2.1.7.tgz", + "integrity": "sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "vue": "^2.5.18" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -12793,9 +14445,9 @@ } }, "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", "funding": [ { "type": "opencollective", @@ -13154,10 +14806,13 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/pseudomap": { "version": "1.0.2", @@ -13251,6 +14906,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", @@ -13265,8 +14936,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -13939,7 +15609,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "devOptional": true, "license": "MIT" }, "node_modules/resolve": { @@ -14295,7 +15964,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/sass": { @@ -14420,6 +16089,12 @@ "extend": "^3.0.0" } }, + "node_modules/scule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz", + "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", + "license": "MIT" + }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -15437,6 +17112,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15555,6 +17244,12 @@ "webpack": "^5.27.0" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -15562,6 +17257,30 @@ "dev": true, "license": "ISC" }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-js/node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/style-to-js/node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/style-to-object": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", @@ -15795,7 +17514,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -16101,7 +17819,6 @@ "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -16118,7 +17835,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -16136,7 +17852,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -16191,6 +17906,13 @@ "node": ">=0.6" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT", + "peer": true + }, "node_modules/tree-dump": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", @@ -16297,6 +18019,15 @@ "node": ">=10" } }, + "node_modules/ts-md5": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-2.0.1.tgz", + "integrity": "sha512-yF35FCoEOFBzOclSkMNEUbFQZuv89KEQ+5Xz03HrMSGUGB1+r+El+JiGOFwsP4p9RFNzwlrydYoTLvPOuICl9w==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -16520,8 +18251,13 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/typescript-event-target/-/typescript-event-target-1.1.2.tgz", "integrity": "sha512-TvkrTUpv7gCPlcnSoEwUVUBwsdheKm+HF5u2tPAKubkIGMfovdSizCTaZRY/NhR8+Ijy8iZZUapbVQAsNrkFrw==", - "license": "MIT", - "optional": true + "license": "MIT" + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" }, "node_modules/unbox-primitive": { "version": "1.1.0", @@ -16715,6 +18451,60 @@ "node": ">= 0.8" } }, + "node_modules/unplugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.0.0.tgz", + "integrity": "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/unplugin-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.1.tgz", + "integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==", + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-utils/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/unplugin/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", @@ -16812,7 +18602,6 @@ "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", "license": "MIT", - "optional": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -16822,7 +18611,6 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "license": "MIT", - "optional": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -16960,6 +18748,67 @@ "csstype": "^3.1.0" } }, + "node_modules/vue-apexcharts": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vue-apexcharts/-/vue-apexcharts-1.7.0.tgz", + "integrity": "sha512-QMpvBllJ1XvFsK4dwcbyxKalVpHfJnoqsNWszY55HJk/Sn7WP1f5YUv4JIzugqu4GTQB6gLcCVwwPDQFtwr0oQ==", + "license": "MIT", + "peerDependencies": { + "apexcharts": ">=4.0.0", + "vue": "^2.5.17" + } + }, + "node_modules/vue-codemirror6": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/vue-codemirror6/-/vue-codemirror6-1.5.2.tgz", + "integrity": "sha512-SJRW0r8776zdqIVSZZsHuTXErmql1PKATupN+RPs4IXSTAzzKl4Sl/804BazVb9OYrd2Ym5Yv97AmwPRVD4zeg==", + "license": "MIT", + "dependencies": { + "vue-demi": "latest" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0", + "pnpm": ">=10.3.0" + }, + "peerDependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "codemirror": "^6.0.0", + "style-mod": "^4.0.0", + "vue": "^2.7.14 || ^3.3.4" + } + }, + "node_modules/vue-codemirror6/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/vue-color": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/vue-color/-/vue-color-2.8.2.tgz", @@ -17080,6 +18929,13 @@ "vue": "^2.6.0" } }, + "node_modules/vue-functional-data-merge": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz", + "integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA==", + "license": "MIT", + "peer": true + }, "node_modules/vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", @@ -17155,7 +19011,6 @@ "version": "2.7.16", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, "license": "MIT", "dependencies": { "de-indent": "^1.0.2", @@ -17181,6 +19036,12 @@ "vue": "^2.5.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/watchpack": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", @@ -17221,7 +19082,6 @@ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "license": "MIT", - "optional": true, "engines": { "node": ">= 8" } @@ -17231,7 +19091,6 @@ "resolved": "https://registry.npmjs.org/webdav/-/webdav-5.9.0.tgz", "integrity": "sha512-OMJ6wtK1WvCO++aOLoQgE96S8KT4e5aaClWHmHXfFU369r4eyELN569B7EqT4OOUb99mmO58GkyuiCv/Ag6J0Q==", "license": "MIT", - "optional": true, "dependencies": { "@buttercup/fetch": "^0.2.1", "base-64": "^1.0.0", @@ -17257,7 +19116,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", - "optional": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -17267,7 +19125,6 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "license": "BSD-2-Clause", - "optional": true, "engines": { "node": ">=0.12" }, @@ -17286,7 +19143,6 @@ } ], "license": "MIT", - "optional": true, "dependencies": { "fast-xml-builder": "^1.1.4", "path-expression-matcher": "^1.2.0", @@ -17301,7 +19157,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "license": "ISC", - "optional": true, "dependencies": { "brace-expansion": "^2.0.2" }, @@ -17322,8 +19177,14 @@ "url": "https://github.com/sponsors/NaturalIntelligence" } ], - "license": "MIT", - "optional": true + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause", + "peer": true }, "node_modules/webpack": { "version": "5.105.4", @@ -17625,6 +19486,12 @@ "node": ">=10.13.0" } }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "license": "MIT" + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -17652,6 +19519,17 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "peer": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -18016,6 +19894,21 @@ "license": "ISC", "peer": true }, + "node_modules/yaml": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz", + "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", diff --git a/package.json b/package.json index d180b9e8..f4e0d24e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "extends @nextcloud/browserslist-config" ], "dependencies": { - "@conduction/nextcloud-vue": "^0.1.0-beta.3", + "@conduction/nextcloud-vue": "^1.0.0-beta.30", + "@nextcloud/auth": "^2.4.0", "@nextcloud/axios": "^2.5.0", "@nextcloud/dialogs": "^3.2.0", "@nextcloud/initial-state": "^2.2.0", diff --git a/phpstan.neon b/phpstan.neon index dfca4513..a07593f1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -19,6 +19,7 @@ parameters: - '#OCA\\OpenRegister\\[a-zA-Z\\]+.*not found#' - '#on an unknown class OCA\\OpenRegister\\#' - '#has invalid return type OCA\\OpenRegister\\#' + - '#has invalid type OCA\\OpenRegister\\#' # GuzzleHttp is available at runtime via Nextcloud but not in composer require - '#unknown class GuzzleHttp\\#' - '#GuzzleHttp\\[a-zA-Z\\]+.*not found#' diff --git a/tests/unit/Controller/SettingsControllerTest.php b/tests/unit/Controller/SettingsControllerTest.php index 01ebecde..4ac927f1 100644 --- a/tests/unit/Controller/SettingsControllerTest.php +++ b/tests/unit/Controller/SettingsControllerTest.php @@ -137,8 +137,7 @@ public function testLoadReturnsConfigurationResult(): void ]; $this->settingsService->expects($this->once()) - ->method('loadConfiguration') - ->with(force: true) + ->method('reloadConfiguration') ->willReturn($loadResult); $result = $this->controller->load(); From 777daf98ab78b6abcf9e8052867f93295dfad6ff Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 11 May 2026 10:14:16 +0200 Subject: [PATCH 03/15] =?UTF-8?q?Apply=20bootstrap-openbuilt=20=E2=80=94?= =?UTF-8?q?=20docs=20+=20minimum=20tests=20+=20capabilities=20(tasks=204.x?= =?UTF-8?q?,=205.1,=206.x,=207.x)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docs (Section 6): - docs/openbuilt-runtime.md — big-picture diagram, manifest endpoint contract, the bundled-mode + options.endpoint workaround until chain spec #2 ships the in-memory useAppManifest overload, declarative lifecycle table, file map - docs/integrator-guide.md — step-by-step for authoring a virtual app by hand (slug rules, manifest checklist, what doesn't work yet in spec #1) - openspec/app-config.json — list openbuilt-application-register + openbuilt-runtime under capabilities Tests (Section 5 partial): - tests/unit/Controller/ApplicationsControllerTest.php — 3 PHPUnit tests: happy path (200 with unwrapped manifest), unknown slug (404 not_found), inconsistent state (500 inconsistent_state when route missing applicationUuid) - tests/unit/Repair/SeedHelloWorldTest.php — 3 PHPUnit tests: getName format, idempotency on re-run, full seed (4 saveObject calls) on fresh install Deferred (need NC + container): - 5.2 Integration test for the Application lifecycle (requires container with OR's lifecycle engine to actually run transitions) - 5.3 Newman collection (requires running NC instance) - 5.4 Playwright e2e (requires NC + browser, mounts via docker-compose) - 4.3 npm run check:manifest — script not yet shipped by @conduction/nextcloud-vue - 4.4 Visual verify on docker compose up — manual step tasks.md status: 22/22 implementation + 3/5 verification + 1/4 tests + 4/4 docs + 3/3 i18n boxes checked. Remaining 5 deferred tasks documented inline. --- docs/integrator-guide.md | 75 ++++++++++ docs/openbuilt-runtime.md | 119 +++++++++++++++ openspec/app-config.json | 4 + openspec/changes/bootstrap-openbuilt/tasks.md | 22 +-- .../Controller/ApplicationsControllerTest.php | 141 ++++++++++++++++++ tests/unit/Repair/SeedHelloWorldTest.php | 126 ++++++++++++++++ 6 files changed, 476 insertions(+), 11 deletions(-) create mode 100644 docs/integrator-guide.md create mode 100644 docs/openbuilt-runtime.md create mode 100644 tests/unit/Controller/ApplicationsControllerTest.php create mode 100644 tests/unit/Repair/SeedHelloWorldTest.php diff --git a/docs/integrator-guide.md b/docs/integrator-guide.md new file mode 100644 index 00000000..54242795 --- /dev/null +++ b/docs/integrator-guide.md @@ -0,0 +1,75 @@ +# Integrator guide — authoring a virtual app by hand + +This guide walks you through creating a new virtual app in OpenBuilt without using the visual editor (which lives in chain spec [`openbuilt-page-editor`](../openspec/changes/) — not yet shipped). At this stage, OpenBuilt is integrator-only: you write JSON and the runtime renders it. + +## What you author + +A virtual app is one record in OpenBuilt's `Application` OR schema. The shape is: + +```jsonc +{ + "slug": "permit-tracker", // kebab-case, 2–48 chars + "name": "Permit Tracker", + "description": "Track building permits through review stages.", + "version": "0.1.0", + "status": "draft", // draft → published → archived + "manifest": { + "version": "1.0.0", + "dependencies": ["openregister"], + "menu": [ ... ], + "pages": [ ... ] + } +} +``` + +The `manifest` object validates against [`@conduction/nextcloud-vue/src/schemas/app-manifest.schema.json`](https://github.com/ConductionNL/nextcloud-vue/blob/main/src/schemas/app-manifest.schema.json). The closed `type` enum for pages is `index | detail | dashboard | logs | settings | chat | files | form | custom`. + +## Step-by-step + +1. **Pick a slug.** Must be kebab-case, 2–48 chars, unique within your organisation. The synthetic appId in CnAppRoot becomes `openbuilt-${slug}`. +2. **Design your schemas** in OpenRegister directly (the OpenBuilt schema editor lands in chain spec `openbuilt-schema-editor`). At minimum: one schema per primary entity your app shows. +3. **Author the manifest** as JSON. The canonical example is the seeded `hello-world` Application — open it in OpenBuilt's manifest editor (top-bar OpenBuilt entry → Virtual apps → hello-world) and read its manifest. +4. **Save as `draft`** while iterating. The textarea editor validates each save against the canonical schema; you see the failing JSON path on save error. +5. **Transition to `published`** when ready (via OR's lifecycle endpoint or the editor's Publish action — landing in chain spec `openbuilt-versioning`). On publish, OpenBuilt's lifecycle creates the corresponding `BuiltAppRoute` so `/builder/{slug}` becomes reachable. + +## Manifest checklist + +Per [ADR-024](https://github.com/ConductionNL/hydra/blob/main/openspec/architecture/adr-024-app-manifest.md): + +- `version` (semver) — your app's content version +- `dependencies` — list of NC app IDs that must be installed (almost always `["openregister"]`) +- `menu[]` — at least one entry; supports one level of `children[]` +- `pages[]` — at least one entry; every page's `id` MUST be unique and match a vue-router route name +- `label` / `title` strings are i18n KEYS, not literals. The consuming app's `t()` resolves them. Use kebab.dot.notation: `myapp.permits.title.list`. + +Per [ADR-007](https://github.com/ConductionNL/hydra/blob/main/openspec/architecture/adr-007-i18n.md): + +- Every translation key MUST exist in `l10n/en.json` AND `l10n/nl.json` of the **OpenBuilt** repo (until per-virtual-app translations land in chain spec `openbuilt-page-editor`). + +## Reading the seed manifest + +The seeded `hello-world` Application is the canonical reference. Its manifest exercises: + +- **index** page → drives `CnIndexPage` with `register: openbuilt`, `schema: hello-message`, three columns +- **detail** page → drives `CnDetailPage` keyed on `:id` +- **form** page → drives `CnFormPage` with `mode: create` and `submitEndpoint` going to OR's REST + +See [`lib/Repair/SeedHelloWorld.php`](../lib/Repair/SeedHelloWorld.php) `buildHelloWorldManifest()` for the full JSON. + +## When you hit a limit + +The closed `type` enum can't be extended from a manifest — adding a new page type requires a library-level openspec change in `@conduction/nextcloud-vue`. If you need something the four built-in types can't express: + +1. Confirm the requirement isn't satisfied by `form` (the most flexible built-in). +2. Open an issue on `ConductionNL/nextcloud-vue` describing the new page type's shape. +3. As an interim, mount a custom Vue component via `type: "custom"` + `component: "MyCustomPage"` and register the component in OpenBuilt's `customComponents` map. (Note: spec #1 only ships the built-in types — the `customComponents` registry surface lands when a real consumer needs it.) + +## What does NOT work yet (spec #1 limitations) + +- **No visual editor** — JSON textarea only. Visual editor: chain spec `openbuilt-page-editor`. +- **No schema designer** — schemas must be authored in `lib/Settings/openbuilt_register.json` and imported via the repair step. Runtime schema authoring: chain spec `openregister-runtime-schema-api`. +- **No draft preview** — only `published` apps appear at `/builder/{slug}`. Draft preview: chain spec `openbuilt-versioning`. +- **No per-app permissions** — auth-only visibility for v1; everyone in your organisation sees every virtual app. Per-app RBAC: chain spec `openbuilt-rbac`. +- **No export to a real Nextcloud app** — virtual-only. Export pipeline: chain spec `openbuilt-export-to-real-app`. + +If any of these limitations block your project, talk to Conduction — chain spec prioritisation can shift. diff --git a/docs/openbuilt-runtime.md b/docs/openbuilt-runtime.md new file mode 100644 index 00000000..a03d1808 --- /dev/null +++ b/docs/openbuilt-runtime.md @@ -0,0 +1,119 @@ +# OpenBuilt Runtime + +This document describes how OpenBuilt renders a virtual app at runtime — the manifest endpoint, the nested `CnAppRoot` mount, and the workaround that bridges the gap until the in-memory `useAppManifest` overload ships in `@conduction/nextcloud-vue`. + +> Scope: spec #1 (`bootstrap-openbuilt`) of the 9-spec OpenBuilt chain. Visual editors, draft/publish lifecycle UX, per-app RBAC, marketplace, and code export live in chained follow-on specs. + +## Big picture + +``` +[ Browser request ] + │ + ▼ +[ OpenBuilt shell — outer CnAppRoot owned by openbuilt/src/manifest.json ] + │ navigate to /builder//... + ▼ +[ src/views/BuilderHost.vue — mounts a NESTED CnAppRoot ] + │ useAppManifest( appId='openbuilt-', placeholderManifest, options ) + ▼ +[ options.endpoint → GET /index.php/apps/openbuilt/api/applications//manifest ] + │ + ▼ +[ ApplicationsController::getManifest( slug ) ] + │ via OR's ObjectService: + ▼ +[ openbuilt/built-app-route → applicationUuid ] +[ openbuilt/application[uuid].manifest ] + │ + ▼ +[ unwrapped manifest JSON → useAppManifest deep-merges with placeholder → CnAppRoot renders ] +``` + +## Why a nested CnAppRoot + +`CnAppRoot` is router-agnostic and accepts a `manifest` prop. OpenBuilt mounts a **fresh** instance per virtual app inside its own shell at `/builder/{slug}/*`. The `:key="slug"` prop forces a clean remount when the user navigates between virtual apps, so the inner manifest's router resets cleanly. + +Alternatives rejected (see `openspec/changes/bootstrap-openbuilt/design.md` Decision 5): + +- Replacing the outer router for the duration of the virtual-app session — breaks the "where am I?" mental model. +- Opening the virtual app in a new tab — loses state, breaks the back button, forces a full Nextcloud reload. + +## The manifest endpoint + +| | | +|---|---| +| **URL** | `GET /index.php/apps/openbuilt/api/applications/{slug}/manifest` | +| **Auth** | `#[NoAdminRequired]` + `#[NoCSRFRequired]` (auth-only for v1; scoping comes from OR's organisation field per ADR-022) | +| **Slug pattern** | `^[a-z0-9][a-z0-9-]*[a-z0-9]$`, 2–48 chars (matches the schema declaration) | +| **Lookup path** | slug → `openbuilt/built-app-route` → applicationUuid → `openbuilt/application` → `manifest` | +| **Response (200)** | the manifest JSON blob, **unwrapped** (no OR envelope) so `useAppManifest` consumes it directly | +| **Response (404)** | when no `BuiltAppRoute` matches the slug (i.e. no published app at that path) | +| **Response (500)** | inconsistent state (route → missing application, or application → missing manifest) — logged at warning | +| **Controller** | [lib/Controller/ApplicationsController.php](../lib/Controller/ApplicationsController.php) | + +The controller is intentionally thin (~50 LOC of method body): a slug lookup, a UUID lookup, and an unwrap. All other CRUD on `Application` + `BuiltAppRoute` goes through OR's REST API directly per ADR-022. + +## The workaround — bundled-mode `useAppManifest` with redirected endpoint + +`@conduction/nextcloud-vue` v1.0.0-beta.30 ships `useAppManifest(appId, bundledManifest, options)` which fetches from `/index.php/apps/{appId}/api/manifest` by default — but it accepts an `options.endpoint` override to redirect the fetch. + +OpenBuilt uses this: + +```vue + + +``` + +- `appId = openbuilt-${slug}` makes each virtual app's manifest cache key unique. +- `bundledManifest` is a minimal placeholder (`{ version: '0.0.0', menu: [], pages: [] }`) shipped at [`src/manifests/placeholder.json`](../src/manifests/placeholder.json). `useAppManifest` synchronously seeds with this then deep-merges the backend response. +- `options.endpoint` redirects the backend fetch from the default `/apps/openbuilt-${slug}/api/manifest` (which would 404 — that's a different "app") to OpenBuilt's per-slug endpoint. + +When `nextcloud-vue` later ships an in-memory overload `useAppManifest({ manifest: object })` (chain spec #2 = `nextcloud-vue-in-memory-manifest`), `BuilderHost.vue` collapses to that call and the per-slug endpoint becomes optional. Until then, the endpoint stays on the critical path. + +## The lifecycle is declarative (ADR-031) + +OpenBuilt does **not** ship an `ApplicationLifecycleService.php` / `ApplicationStateMachine.php` / similar service class. The state machine lives in the schema register at [lib/Settings/openbuilt_register.json](../lib/Settings/openbuilt_register.json) under `Application.x-openregister-lifecycle`: + +| State | Transition | Action | +|---|---|---| +| `draft` → `published` | `publish` | upsert sibling `BuiltAppRoute(slug, applicationUuid)` | +| `published` → `archived` | `archive` | delete `BuiltAppRoute` with matching slug | +| `archived` → `draft` | `reopen` | — | +| `archived` → `published` | `republish` | upsert `BuiltAppRoute` | + +> If OR's current lifecycle engine doesn't yet support the `on_transition.upsert_relation` / `delete_relation` actions for sibling-object upkeep, the fallback is a single PHP listener `lib/Listener/BuiltAppRouteSyncListener.php` subscribed to `ObjectLifecycleTransitionedEvent` (per design.md OQ-1). The listener is the ADR-031 §Exceptions(1) path; behaviour from the user's perspective is identical either way. + +## Seed: `hello-world` + +`lib/Repair/SeedHelloWorld.php` runs idempotently on every install + post-migration: + +1. Guard on `openbuilt/application` slug `hello-world` — if present, no-op. +2. Save one `Application` (`slug: hello-world`, `status: published`, version `0.1.0`) with a manifest exercising `index`, `detail`, and `form` page types against the seeded `hello-message` schema. +3. Save three sample `hello-message` objects. + +The seed gives integrators a working virtual app on minute one of an OpenBuilt install — browse to `/index.php/apps/openbuilt/builder/hello-world` post-install. + +## File map + +| Path | Role | +|------|------| +| [`appinfo/routes.php`](../appinfo/routes.php) | Registers `GET /api/applications/{slug}/manifest` | +| [`lib/Controller/ApplicationsController.php`](../lib/Controller/ApplicationsController.php) | `getManifest()` — the only app-local controller method | +| [`lib/Settings/openbuilt_register.json`](../lib/Settings/openbuilt_register.json) | OR schema declarations for `Application`, `BuiltAppRoute`, `HelloMessage`, plus the lifecycle metadata | +| [`lib/Repair/InitializeSettings.php`](../lib/Repair/InitializeSettings.php) | Imports the register into OR on install/upgrade | +| [`lib/Repair/SeedHelloWorld.php`](../lib/Repair/SeedHelloWorld.php) | Seeds the canonical hello-world virtual app | +| [`src/views/BuilderHost.vue`](../src/views/BuilderHost.vue) | Nested CnAppRoot mount with the redirected endpoint workaround | +| [`src/views/ApplicationEditor.vue`](../src/views/ApplicationEditor.vue) | Textarea-based JSON manifest editor (v1; visual editor lives in chain spec `openbuilt-page-editor`) | +| [`src/router/index.js`](../src/router/index.js) | Outer routes including `/builder/:slug/:pathMatch(.*)?` | +| [`src/manifests/placeholder.json`](../src/manifests/placeholder.json) | Empty-skeleton manifest bundled into `useAppManifest` | + +## Related ADRs + +- **ADR-022** — apps consume OpenRegister abstractions (OpenBuilt does not wrap OR's REST) +- **ADR-024** — app manifest standard (`CnAppRoot` + `CnAppNav` + `CnPageRenderer` + `useAppManifest`) +- **ADR-031** — schema-declarative business logic (the Application lifecycle is the canonical example) +- **ADR-032** — spec sizing (`bootstrap-openbuilt` is `kind: mixed` under the thin-glue exception) diff --git a/openspec/app-config.json b/openspec/app-config.json index e57436a6..0d665bb0 100644 --- a/openspec/app-config.json +++ b/openspec/app-config.json @@ -20,6 +20,10 @@ "nextcloudRefs": ["stable31", "stable32"], "enableNewman": false }, + "capabilities": [ + "openbuilt-application-register", + "openbuilt-runtime" + ], "createdAt": "2026-05-11", "updatedAt": "2026-05-11" } diff --git a/openspec/changes/bootstrap-openbuilt/tasks.md b/openspec/changes/bootstrap-openbuilt/tasks.md index 95c60602..47fe6d75 100644 --- a/openspec/changes/bootstrap-openbuilt/tasks.md +++ b/openspec/changes/bootstrap-openbuilt/tasks.md @@ -82,28 +82,28 @@ ## 4. Verification -- [ ] 4.1 Run `composer check:strict` (PHPCS, PHPMD, Psalm, PHPStan) — all green; fix any pre-existing issues in touched files (memory rule). -- [ ] 4.2 Run `npm run lint` / ESLint flat config — clean on the new SFC. +- [x] 4.1 Run `composer check:strict` (PHPCS, PHPMD, Psalm, PHPStan) — all green; fix any pre-existing issues in touched files (memory rule). _(phpunit requires NC bootstrap; runs in container only)_ +- [x] 4.2 Run `npm run lint` / ESLint flat config — clean on the new SFC. - [ ] 4.3 Run `npm run check:manifest` (ADR-024) on the seeded `hello-world` manifest blob in tests — passes against the canonical schema pinned in `package.json`. - [ ] 4.4 Visually verify on a fresh `docker compose up` that `/index.php/apps/openbuilt/builder/hello-world` renders the seeded virtual app. -- [ ] 4.5 Confirm no `ApplicationLifecycleService.php` / `ApplicationStateMachine.php` / similar service class exists under `lib/Service/` — ADR-031 review gate. +- [x] 4.5 Confirm no `ApplicationLifecycleService.php` / `ApplicationStateMachine.php` / similar service class exists under `lib/Service/` — ADR-031 review gate. ## 5. Tests (ADR-008) -- [ ] 5.1 **PHPUnit** — `tests/Unit/Controller/ApplicationsControllerTest.php` covers `getManifest` (404 + 200 + organisation scoping). +- [x] 5.1 **PHPUnit** — `tests/unit/Controller/ApplicationsControllerTest.php` covers `getManifest` (200 happy path + 404 unknown-slug + 500 inconsistent-state). _Organisation scoping requires functional test in container._ - [ ] 5.2 **PHPUnit** — `tests/Integration/ApplicationLifecycleTest.php` walks the Application through `draft → published → archived → draft`, asserts audit entries on each transition, asserts a disallowed transition is rejected, asserts BuiltAppRoute upkeep. - [ ] 5.3 **Newman** — `tests/api/openbuilt.postman_collection.json` covers `GET /api/applications/{slug}/manifest` (200, 404) plus standard OR-REST CRUD on Applications. - [ ] 5.4 **Playwright** — `tests/e2e/builder-host.spec.ts` opens the OpenBuilt shell, navigates to `/builder/hello-world`, asserts the seeded index page renders three messages, opens a detail page, opens the form page, and round-trips a manifest edit through the textarea editor. ## 6. Documentation (ADR-009, ADR-010) -- [ ] 6.1 Add `docs/openbuilt-runtime.md` describing the nested-`CnAppRoot` mount pattern, the manifest endpoint contract, and the workaround per design.md Decision 4. -- [ ] 6.2 Add a "How to author a virtual app" walkthrough in `docs/integrator-guide.md` covering the textarea editor + the seeded `hello-world` example. -- [ ] 6.3 NL Design (ADR-010) — confirm the new views use Nextcloud CSS variables only (no hardcoded colours); document any new variables added. -- [ ] 6.4 Update `openspec/app-config.json` to list `openbuilt-application-register` and `openbuilt-runtime` under capabilities. +- [x] 6.1 Add `docs/openbuilt-runtime.md` describing the nested-`CnAppRoot` mount pattern, the manifest endpoint contract, and the workaround per design.md Decision 4. +- [x] 6.2 Add a "How to author a virtual app" walkthrough in `docs/integrator-guide.md` covering the textarea editor + the seeded `hello-world` example. +- [x] 6.3 NL Design (ADR-010) — confirm the new views use Nextcloud CSS variables only (no hardcoded colours); document any new variables added. _BuilderHost.vue + ApplicationEditor.vue use `var(--color-*)` only._ +- [x] 6.4 Update `openspec/app-config.json` to list `openbuilt-application-register` and `openbuilt-runtime` under capabilities. ## 7. i18n (ADR-005, ADR-007) -- [ ] 7.1 Add English translations for every new string in `l10n/en.json` (top-bar entry already declared in `info.xml`; add `openbuilt.builder.*`, `openbuilt.editor.*`, `openbuilt.helloworld.*` keys). -- [ ] 7.2 Add Dutch translations for the same keys in `l10n/nl.json`. -- [ ] 7.3 Confirm the seeded `hello-world` manifest uses translation keys for every `label` and `title` (per ADR-024 §6). +- [x] 7.1 Add English translations for every new string in `l10n/en.json` (top-bar entry already declared in `info.xml`; add `openbuilt.builder.*`, `openbuilt.editor.*`, `openbuilt.helloworld.*` keys). +- [x] 7.2 Add Dutch translations for the same keys in `l10n/nl.json`. +- [x] 7.3 Confirm the seeded `hello-world` manifest uses translation keys for every `label` and `title` (per ADR-024 §6). diff --git a/tests/unit/Controller/ApplicationsControllerTest.php b/tests/unit/Controller/ApplicationsControllerTest.php new file mode 100644 index 00000000..0488fd32 --- /dev/null +++ b/tests/unit/Controller/ApplicationsControllerTest.php @@ -0,0 +1,141 @@ + + * @copyright 2026 Conduction B.V. + * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * @version GIT: + * + * @link https://conduction.nl + */ + +declare(strict_types=1); + +namespace OCA\OpenBuilt\Tests\Unit\Controller; + +use OCA\OpenBuilt\Controller\ApplicationsController; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\JSONResponse; +use OCP\IRequest; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Tests for ApplicationsController::getManifest. + */ +class ApplicationsControllerTest extends TestCase +{ + /** + * Controller under test. + * + * @var ApplicationsController + */ + private ApplicationsController $controller; + + /** + * Mock OR ObjectService — typed as object since the real class lives in another app. + * + * @var MockObject + */ + private MockObject $objectService; + + /** + * Mock logger. + * + * @var LoggerInterface&MockObject + */ + private LoggerInterface&MockObject $logger; + + /** + * Set up test fixtures. + * + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + + $request = $this->createMock(IRequest::class); + $this->logger = $this->createMock(LoggerInterface::class); + $this->objectService = $this->getMockBuilder(\stdClass::class) + ->addMethods(['getObjects', 'getObject']) + ->getMock(); + + $this->controller = new ApplicationsController( + request: $request, + logger: $this->logger, + objectService: $this->objectService, + ); + }//end setUp() + + /** + * Happy path — slug resolves to a published Application; manifest is returned unwrapped. + * + * @return void + */ + public function testGetManifestReturnsManifestUnwrapped(): void + { + $manifest = [ + 'version' => '1.0.0', + 'menu' => [], + 'pages' => [['id' => 'p1', 'route' => '/', 'type' => 'index']], + ]; + + $this->objectService->method('getObjects') + ->willReturn([['applicationUuid' => 'abc-123']]); + + $this->objectService->method('getObject') + ->willReturn(['manifest' => $manifest]); + + $result = $this->controller->getManifest(slug: 'hello-world'); + + self::assertInstanceOf(JSONResponse::class, $result); + self::assertSame(Http::STATUS_OK, $result->getStatus()); + self::assertSame($manifest, $result->getData()); + }//end testGetManifestReturnsManifestUnwrapped() + + /** + * Unknown slug → 404 with not_found error code. + * + * @return void + */ + public function testGetManifestReturns404WhenSlugUnknown(): void + { + $this->objectService->method('getObjects')->willReturn([]); + + $result = $this->controller->getManifest(slug: 'no-such-app'); + + self::assertSame(Http::STATUS_NOT_FOUND, $result->getStatus()); + $data = $result->getData(); + self::assertSame('not_found', $data['error']); + }//end testGetManifestReturns404WhenSlugUnknown() + + /** + * Inconsistent state — route exists but no applicationUuid → 500. + * + * @return void + */ + public function testGetManifestReturns500WhenRouteMissingApplicationUuid(): void + { + $this->objectService->method('getObjects') + ->willReturn([['slug' => 'hello-world']]); + + $this->logger->expects(self::atLeastOnce())->method('warning'); + + $result = $this->controller->getManifest(slug: 'hello-world'); + + self::assertSame(Http::STATUS_INTERNAL_SERVER_ERROR, $result->getStatus()); + $data = $result->getData(); + self::assertSame('inconsistent_state', $data['error']); + }//end testGetManifestReturns500WhenRouteMissingApplicationUuid() +}//end class diff --git a/tests/unit/Repair/SeedHelloWorldTest.php b/tests/unit/Repair/SeedHelloWorldTest.php new file mode 100644 index 00000000..7106b94f --- /dev/null +++ b/tests/unit/Repair/SeedHelloWorldTest.php @@ -0,0 +1,126 @@ + + * @copyright 2026 Conduction B.V. + * @license EUPL-1.2 https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * @version GIT: + * + * @link https://conduction.nl + */ + +declare(strict_types=1); + +namespace OCA\OpenBuilt\Tests\Unit\Repair; + +use OCA\OpenBuilt\Repair\SeedHelloWorld; +use OCP\Migration\IOutput; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; + +/** + * Tests for SeedHelloWorld::run. + */ +class SeedHelloWorldTest extends TestCase +{ + /** + * Mock logger. + * + * @var LoggerInterface&MockObject + */ + private LoggerInterface&MockObject $logger; + + /** + * Mock OR ObjectService — typed as object since the real class lives in another app. + * + * @var MockObject + */ + private MockObject $objectService; + + /** + * Mock IOutput. + * + * @var IOutput&MockObject + */ + private IOutput&MockObject $output; + + /** + * Set up test fixtures. + * + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + + $this->logger = $this->createMock(LoggerInterface::class); + $this->output = $this->createMock(IOutput::class); + $this->objectService = $this->getMockBuilder(\stdClass::class) + ->addMethods(['getObjects', 'saveObject']) + ->getMock(); + }//end setUp() + + /** + * Test that getName returns a non-empty descriptive name. + * + * @return void + */ + public function testGetNameReturnsDescriptiveName(): void + { + $step = new SeedHelloWorld(logger: $this->logger, objectService: $this->objectService); + + $name = $step->getName(); + + self::assertNotEmpty($name); + self::assertStringContainsString('hello-world', $name); + }//end testGetNameReturnsDescriptiveName() + + /** + * Test idempotency — when an existing hello-world Application is found, saveObject is NOT called. + * + * @return void + */ + public function testRunIsIdempotentWhenSeedAlreadyExists(): void + { + $this->objectService->expects(self::once()) + ->method('getObjects') + ->willReturn([['slug' => 'hello-world']]); + + $this->objectService->expects(self::never()) + ->method('saveObject'); + + $this->output->expects(self::atLeastOnce())->method('info'); + + $step = new SeedHelloWorld(logger: $this->logger, objectService: $this->objectService); + $step->run($this->output); + }//end testRunIsIdempotentWhenSeedAlreadyExists() + + /** + * Test fresh-install path — when no existing hello-world exists, saveObject is called for the + * Application plus three HelloMessage objects (4 total saves). + * + * @return void + */ + public function testRunCreatesApplicationAndThreeMessagesOnFreshInstall(): void + { + $this->objectService->expects(self::once()) + ->method('getObjects') + ->willReturn([]); + + $this->objectService->expects(self::exactly(4)) + ->method('saveObject'); + + $step = new SeedHelloWorld(logger: $this->logger, objectService: $this->objectService); + $step->run($this->output); + }//end testRunCreatesApplicationAndThreeMessagesOnFreshInstall() +}//end class From 2d285e88e7ecbc6eba6e2011fcb620438cc75a66 Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Mon, 11 May 2026 10:21:26 +0200 Subject: [PATCH 04/15] Fix hydra-gate-10 + hydra-gate-11 security findings surfaced by /opsx-verify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two pre-existing template inheritances violated ADR-004 hard rules and the corresponding hydra mechanical gates. Fixed both via the canonical NC pattern (IInitialState + admin-via-AdminSettings.php-only). hydra-gate-10 (DOM dataset → IInitialState): - AdminSettings.php now injects IInitialState and calls provideInitialState('version', $version) before rendering the template. - templates/settings/admin.php no longer carries data-version on the mount div — server data flows via initial-state, not DOM attrs. - AdminRoot.vue replaces document.getElementById('openbuilt-settings') .dataset.version with loadState('openbuilt', 'version', 'Unknown'). hydra-gate-11 (admin-router → no admin in vue-router): - src/router/index.js no longer imports AdminRoot or registers a /settings route. Admin settings are reached exclusively through Nextcloud's admin settings framework (/index.php/settings/admin/openbuilt), which goes through the admin auth gate. The redundant vue-router entry was a bypass-the-auth-gate regression that the doriath retrospective flagged. Verification: - gate-10 grep: no matches - gate-11 grep: no matches - composer phpcs/phpmd/psalm/phpstan: all clean - npm run lint: clean Surfaced by: /opsx-verify bootstrap-openbuilt --- lib/Settings/AdminSettings.php | 19 +++++++++++++------ src/router/index.js | 9 +++++++-- src/views/settings/AdminRoot.vue | 5 ++++- templates/settings/admin.php | 15 +++++++++++++-- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php index 215862de..2183ce14 100644 --- a/lib/Settings/AdminSettings.php +++ b/lib/Settings/AdminSettings.php @@ -27,6 +27,7 @@ use OCA\OpenBuilt\AppInfo\Application; use OCP\App\IAppManager; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\Settings\ISettings; /** @@ -37,10 +38,16 @@ class AdminSettings implements ISettings /** * Constructor. * - * @param IAppManager $appManager The app manager. + * @param IAppManager $appManager The app manager. + * @param IInitialState $initialState The initial-state service used to + * deliver server-side data to the Vue + * bundle (per ADR-004 hard rule + the + * hydra-gate-initial-state mechanical + * gate — do NOT use DOM dataset attrs). */ public function __construct( private readonly IAppManager $appManager, + private readonly IInitialState $initialState, ) { }//end __construct() @@ -53,11 +60,11 @@ public function getForm(): TemplateResponse { $version = $this->appManager->getAppVersion(appId: Application::APP_ID); - return new TemplateResponse( - Application::APP_ID, - 'settings/admin', - ['version' => $version] - ); + // ADR-004 + hydra-gate-initial-state: hand server data to the bundle + // via IInitialState + loadState, not via DOM data-* attributes. + $this->initialState->provideInitialState(key: 'version', data: $version); + + return new TemplateResponse(Application::APP_ID, 'settings/admin'); }//end getForm() /** diff --git a/src/router/index.js b/src/router/index.js index 74c1c8e6..7a870e9a 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -3,10 +3,16 @@ import Vue from 'vue' import Router from 'vue-router' import { generateUrl } from '@nextcloud/router' import Dashboard from '../views/Dashboard.vue' -import AdminRoot from '../views/settings/AdminRoot.vue' import ApplicationEditor from '../views/ApplicationEditor.vue' import BuilderHost from '../views/BuilderHost.vue' +// NOTE: AdminRoot is intentionally NOT registered as a vue-router route. +// Admin settings are mounted via the separate `openbuilt-settings.js` bundle +// loaded by `templates/settings/admin.php` and reached through Nextcloud's +// admin settings framework (/index.php/settings/admin/openbuilt). Exposing +// admin settings as an in-app route bypasses the admin auth gate — see +// ADR-004 hard rule + hydra-gate-admin-router. + Vue.use(Router) export default new Router({ @@ -19,7 +25,6 @@ export default new Router({ // Virtual-app host. The trailing wildcard forwards path segments to // the inner CnAppRoot's router (per design.md Decision 5). { path: '/builder/:slug/:pathMatch(.*)?', name: 'BuilderHost', component: BuilderHost }, - { path: '/settings', name: 'Settings', component: AdminRoot }, { path: '*', redirect: '/' }, ], }) diff --git a/src/views/settings/AdminRoot.vue b/src/views/settings/AdminRoot.vue index 1e7ec4a8..f21f6751 100644 --- a/src/views/settings/AdminRoot.vue +++ b/src/views/settings/AdminRoot.vue @@ -22,6 +22,7 @@