Skip to content

fix(store): drop the hand-rolled object store; route settings through cnFetchJson - #179

Merged
rubenvdlinde merged 3 commits into
developmentfrom
fix/template-drops-hand-rolled-object-store
Aug 26, 2026
Merged

fix(store): drop the hand-rolled object store; route settings through cnFetchJson#179
rubenvdlinde merged 3 commits into
developmentfrom
fix/template-drops-hand-rolled-object-store

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The template shipped two object stores.

src/store/store.js already created the canonical one with createObjectStore from @conduction/nextcloud-vue. Alongside it, src/store/modules/object.js defined a second useObjectStore as a hand-rolled defineStore('object') doing raw fetch() with a hand-set requesttoken.

Nothing imported the second one — but every app scaffolded from this template inherited it. That is why ADR-071 finds app-local store/modules/object.js variants in six apps and parallel generic stores in two more: the template is the source that kept re-seeding the exact pattern ADR-071 Decisions 1 and 2 delete. ADR-100 Decision 5 makes fixing it the precondition for any leaf migration.

Changes

  • Delete src/store/modules/object.js — dead, and the anti-pattern's seed.
  • settings.jscnFetchJson (ADR-071 Decision 1). URLs still go through generateUrl: cnFetch's own prefixUrl only adds /index.php and does not know the instance webroot, so an install under https://host/nextcloud would break. Handing prefixUrl an already-generated URL is a no-op, so this keeps the correct URL and the library's blessed headers.
  • settings.js gains an error state. Both actions previously returned null on failure — and null was also the legitimate "nothing yet" value, so a settings endpoint returning 500 was indistinguishable from a fresh install. Failures are now logged and observable, while the actions still resolve rather than throw, so a broken endpoint cannot stop the SPA mounting.
  • Bump @conduction/nextcloud-vue ^2.3.0^2.16.0. Required, not cosmetic: cnFetch/cnFetchJson first shipped in v2.11.0 and the installed tree was on 2.2.0, so the import would not have resolved. ^2.16.0 matches openregister and decidesk; the lock resolves 2.17.0.

The spec was wrong in two ways, and is corrected here

  1. It required the deleted module by path, and pinned configure() / registerObjectType() / fetchObjects() — an API the dead module had and the library store does not. The spec described the module nothing imported while the code used the other one.
  2. Its "degrade gracefully" clause required failures to resolve to a safe empty/null value and said nothing about surfacing them — writing the unobservable-failure pattern into a normative requirement. It now requires the safe value and a recorded error.

Verification

npm run build compiles — webpack 5.109.2, 2 pre-existing warnings. Local eslint could not run (the repo's flat config fails against the installed @nextcloud/eslint-config, pre-existing and unrelated); CI will lint.

Refs ADR-071 Decisions 1–2, ADR-026, ADR-100 Decision 5.

… cnFetchJson

The template shipped TWO object stores. `src/store/store.js` already created
the canonical one with `createObjectStore` from @conduction/nextcloud-vue,
while `src/store/modules/object.js` defined a second `useObjectStore` as a
hand-rolled `defineStore('object')` doing raw `fetch()` with a hand-set
`requesttoken`.

Nothing imported the second one — but every app scaffolded from this template
inherited it, which is why ADR-071 finds app-local `store/modules/object.js`
variants in six apps and parallel generic stores in two more. The template was
the source that kept re-seeding the pattern ADR-071 Decisions 1 and 2 delete.

Changes:

- Delete src/store/modules/object.js (dead, and the anti-pattern's seed).
- settings.js now uses cnFetchJson instead of raw fetch + getRequestToken
  (ADR-071 Decision 1). URLs still go through generateUrl, because cnFetch's
  own prefixUrl only adds /index.php and does not know the instance webroot —
  handing it an already-generated URL is a no-op there, so this keeps the
  correct URL AND the library's blessed headers.
- settings.js gains an `error` state. Both actions previously returned null on
  failure, and null was also the legitimate "nothing yet" value, so a settings
  endpoint returning 500 was indistinguishable from a fresh install. Failures
  are now logged AND observable; the actions still resolve rather than throw,
  so a broken endpoint cannot stop the SPA mounting.
- Bump @conduction/nextcloud-vue ^2.3.0 -> ^2.16.0. REQUIRED, not cosmetic:
  cnFetch/cnFetchJson first shipped in v2.11.0, and the installed tree was on
  2.2.0, so the import would not have resolved. ^2.16.0 matches openregister
  and decidesk; the lock resolves 2.17.0.

The spec is corrected in the same commit, because it was wrong in two ways:

- It REQUIRED the deleted module by path, and pinned `configure()` /
  `registerObjectType()` / `fetchObjects()` — an API the dead module had and
  the library store does not. The spec described the module nothing imported
  while the code used the other one.
- Its "degrade gracefully" clause REQUIRED failures to resolve to a safe
  empty/null value and said nothing about surfacing them, writing the
  unobservable-failure pattern into a normative requirement. It now requires
  the safe value AND a recorded error.

Verified: npm run build compiles (webpack 5.109.2, 2 pre-existing warnings).

Refs ADR-071 Decisions 1-2, ADR-026, ADR-100 Decision 5.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/nextcloud-app-template @ eb42d32

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
format
composer ✅ 103/103
npm ✅ 737/737
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-25 22:29 UTC

Download the full PDF report from the workflow artifacts.

…c warnings

gate-47 (security-change-has-tests) flagged the previous commit: it changed
CSRF/transport handling with no test co-change. It was right to.

tests/settings-store.spec.js covers both halves of the fix, because either one
alone is the bug:

  * resolving to null WITHOUT recording      -> the original silent failure
  * recording but THROWING out of the action -> a broken endpoint blocks boot

Arm 4 is the one that would have caught the original defect. It asserts that
'the backend had nothing' and 'the backend failed' are DISTINGUISHABLE, rather
than merely that failure returns null — a test asserting only '=== null' passes
against the broken version unchanged.

VERIFIED AGAINST THE OLD BEHAVIOUR, not just the new one: re-running this exact
spec against a reconstructed silent-failure store fails 4 of 6 arms, with arm 4
reporting 'indistinguishable'. A test that only passes on the fixed code cannot
be shown to detect the defect it was written for.

Wired into check:specs alongside the sibling node specs, so it runs in CI
rather than only by hand.

Also fixes the two eslint warnings the previous commit introduced (the repo
runs --max-warnings 0): a jsdoc block opening with text on the /** line, and a
getter missing its @PARAM.

The spec harness reimplements the action bodies rather than importing pinia,
matching registry.spec.js / manifest-v2.spec.js which run under bare node. That
limit is stated in the file: it pins the CONTRACT, not the module wiring, and
the wiring is covered by the build plus the e2e app-shell spec.
The repo runs `prettier --check` over **/*.js and eslint with --max-warnings 0,
and the new spec satisfied neither. Formatting applied with prettier --write;
the two top-level arrow consts (`bad`, `rejecting`) become function
declarations, which is what antfu/top-level-function requires.

No behaviour change — the spec still passes all six arms, and still fails four
of them against a reconstructed silent-failure store, which is the property
that makes it worth having.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/nextcloud-app-template @ a2a1d41

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
format
composer ✅ 103/103
npm ✅ 737/737
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-26 09:26 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/nextcloud-app-template @ 4a19a2b

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-specs
check-manifest
format
composer ✅ 103/103
npm ✅ 737/737
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-26 10:50 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit 2adc601 into development Aug 26, 2026
81 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/template-drops-hand-rolled-object-store branch August 26, 2026 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant