Remove what the migration left unreachable, and record what it left broken
The shared-wallet shim's fan-out in the data context fed the ORM subscriptions this provider used to open: readGraphs, writeGraphs, protectedScope, protectedGraph and the effect that filled them from storeRegistry. Every entity reads through a Refine backend now, which takes no graph list, so none of it was reachable. Same for findNg, mapUser and mapParticipation -- reading a record into a domain type belongs to a backend's binding, not here. storeRegistry itself stays: the @data multistore scenarios drive it directly. This is debt the migration created, not debt it inherited, which is why it goes rather than waiting for a tidy-up. What the removal COSTS is written where it happened: placement by scope no longer narrows what the app reads. The backend's visibility declaration is where that belongs and nothing honours it yet; applyIsolation is the only narrowing left. And setLike.delete is now marked as the defect it is. It is a no-op lifted from a branch where the fixture seed is off, so nothing needs deleting before it -- false here, where the step that empties the wallet therefore does nothing. Fixing it needs a decision the comment states, because the app exposes no deleteEvent.
This commit is contained in:
@@ -18,8 +18,6 @@ import { useList, useCreate, useUpdate, useDelete } from '@refinedev/core';
|
||||
import { useNextGraph } from './NextGraphContext';
|
||||
import { useAccount, normalizeUsername } from './AccountContext';
|
||||
import { applyIsolation } from '../utils/isolation';
|
||||
import { ensureAccount, resolveReadGraphs, resolveWriteGraph } from '../utils/storeRegistry';
|
||||
import { useShapeWithDefaults, type ShapeScope } from '../hooks/useShapeWithDefaults';
|
||||
import { useBackend } from '../refine/RefineProvider';
|
||||
|
||||
// Multi-document mode (storeRegistry): one document per (account × scope),
|
||||
@@ -96,13 +94,6 @@ function nextId(prefix: string): string {
|
||||
return `${prefix}-${++idCounter}`;
|
||||
}
|
||||
|
||||
function findNg<T extends { "@id": string }>(set: Set<T>, predicate: (item: T) => boolean): T | undefined {
|
||||
for (const item of set) {
|
||||
if (predicate(item)) return item;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// EVENTS are read and written through the selected Refine BACKEND, so the record
|
||||
// shape, the vocabulary and the two identifiers are its business, not this file's
|
||||
// — see refine/providers/types.ts. The binding is read from `useBackend()` inside
|
||||
@@ -111,21 +102,9 @@ function findNg<T extends { "@id": string }>(set: Set<T>, predicate: (item: T) =
|
||||
// backend unswitchable. Everything else in this file still speaks `fp:` directly,
|
||||
// because profiles and participations have not moved to Refine yet.
|
||||
|
||||
const mapUser = (u: FpUserProfile): FpUserData => ({
|
||||
id: u["@id"],
|
||||
name: u.name,
|
||||
initials: u.initials,
|
||||
username: u.username,
|
||||
role: u.role,
|
||||
isPublic: u.isPublic,
|
||||
});
|
||||
|
||||
const mapParticipation = (p: FpParticipation): FpParticipationData => ({
|
||||
id: p["@id"],
|
||||
eventId: p.event,
|
||||
userId: p.user,
|
||||
isConfirmed: p.isConfirmed,
|
||||
});
|
||||
// NO mapUser / mapParticipation HERE ANY MORE. Reading a backend record into a
|
||||
// domain type is the backend's binding (refine/providers/types.ts): the record
|
||||
// shape is its vocabulary, not this file's.
|
||||
|
||||
// ============================================================================
|
||||
// Shared queries builder — same logic for both local and NG modes
|
||||
@@ -291,40 +270,17 @@ function useNgData(): FestipodDataContextValue {
|
||||
// repo in the verifier (enables reads + writes), per the data-layer rule.
|
||||
const privateNuri = session ? `did:ng:${session.private_store_id}` : undefined;
|
||||
|
||||
// Multi-document state (storeRegistry): read fan-out (all accounts' docs per
|
||||
// scope) and the current account's write docs. Populated by the effect below.
|
||||
const [readGraphs, setReadGraphs] = useState<{ protected: string[] }>({ protected: [] });
|
||||
const [writeGraphs, setWriteGraphs] = useState<{ protected?: string }>({});
|
||||
|
||||
useEffect(() => {
|
||||
if (!MULTISTORE || !privateNuri || !username) return;
|
||||
let cancelled = false;
|
||||
(async () => {
|
||||
try {
|
||||
await ensureAccount(username); // create this account's index docs on first sight
|
||||
// Protected = grouped in each account's protected index document.
|
||||
// NO public fan-out any more: events are a Refine resource, and the data
|
||||
// provider addresses them by shape across every graph it can see — it
|
||||
// never takes a graph list, so the public index has no reader left.
|
||||
const [prot, wProt] = await Promise.all([
|
||||
resolveReadGraphs('protected'),
|
||||
resolveWriteGraph(username, 'protected'),
|
||||
]);
|
||||
if (cancelled) return;
|
||||
setReadGraphs({ protected: prot });
|
||||
setWriteGraphs({ protected: wProt });
|
||||
} catch (err) {
|
||||
console.error('[FestipodData] storeRegistry init failed:', err);
|
||||
}
|
||||
})();
|
||||
return () => { cancelled = true; };
|
||||
}, [privateNuri, username]);
|
||||
|
||||
// Scope for profiles + participations, which still read through the ORM.
|
||||
// Mono-store mode collapses them to the private store.
|
||||
const protectedScope: ShapeScope = MULTISTORE
|
||||
? (readGraphs.protected.length ? { graphs: readGraphs.protected } : undefined)
|
||||
: privateNuri;
|
||||
// NO SCOPE WIRING LEFT HERE. The shared-wallet shim's fan-out (readGraphs /
|
||||
// writeGraphs / protectedScope, and the effect that filled them from
|
||||
// storeRegistry) fed the ORM subscriptions this provider used to open. Every
|
||||
// entity now reads through a Refine backend, which takes no graph list, so all
|
||||
// of it became unreachable and is gone. `storeRegistry` itself stays — the
|
||||
// @data multistore scenarios still drive it directly.
|
||||
//
|
||||
// What this COSTS, stated rather than buried: placement by scope no longer
|
||||
// narrows what the app reads. The backend's `visibility` declaration
|
||||
// (refine/providers/types.ts) is where that belongs, and no backend honours it
|
||||
// yet; `applyIsolation` below is the only narrowing still applied.
|
||||
|
||||
// --- Events: read through REFINE -----------------------------------------
|
||||
// `useList` goes to `@ng-org/refine-providers`, which resolves the resource
|
||||
@@ -529,10 +485,9 @@ function useNgData(): FestipodDataContextValue {
|
||||
'| users:', users.length, '| participations:', participations.length,
|
||||
'| selectedEvent:', selectedEvent?.title ?? '(none)');
|
||||
|
||||
// --- Mutations (NG) ---
|
||||
// Participations stay GROUPED in the account's protected index document.
|
||||
// Mono-store mode collapses everything to the private store.
|
||||
const protectedGraph = (MULTISTORE ? writeGraphs.protected : undefined) || privateNuri || '';
|
||||
// --- Mutations: every entity through REFINE ------------------------------
|
||||
// No write graph to resolve any more: the backend creates a document per
|
||||
// record, so nothing here names where a write lands.
|
||||
|
||||
const createEvent = useCallback(async (event: Omit<FpEventData, 'id'>): Promise<FpEventData> => {
|
||||
console.log('[FestipodData] createEvent (Refine):', event.title);
|
||||
|
||||
@@ -119,9 +119,15 @@ function ConnectedHarness() {
|
||||
}));
|
||||
/**
|
||||
* A read-only Set-like over an app-backed array snapshot: supports
|
||||
* `[...x]`, `x.size`, and a no-op `delete`. The "empty wallet" scenario runs
|
||||
* before any seed, so there is nothing for it to delete — and a seeded
|
||||
* record is not this bridge's to remove.
|
||||
* `[...x]`, `x.size`, and `delete`.
|
||||
*
|
||||
* KNOWN DEFECT, recorded rather than left to be rediscovered: `delete` is a
|
||||
* no-op. It came from the sibling branch, where it is justified — there the
|
||||
* fixture seed is off, so the "empty wallet" scenario has nothing to delete.
|
||||
* HERE the seed writes, so that premise is false and the step which empties
|
||||
* the wallet silently does nothing. Fixing it needs a decision, because the
|
||||
* app exposes no `deleteEvent`: the bridge would have to read the app's view
|
||||
* and delete through the ORM, a hybrid worth stating before adopting.
|
||||
*/
|
||||
const setLike = <T,>(snapshot: () => T[]) => ({
|
||||
get size() { return snapshot().length; },
|
||||
|
||||
Reference in New Issue
Block a user