fix(rnotes): resolve global scope for notebook docIds and seeding
The rnotes module has defaultScope: 'global' but several code paths used the raw space slug instead of the resolved scope: - subscribeNotebook() built docIds with space slug (e.g. jeff🎶...) instead of resolved scope (global🎶...), breaking Automerge sync - seedDemoIfEmpty() seeded notebooks under space-scoped paths, orphaning them when the API queries global-scoped prefix - onSpaceCreate() created default notebook under space scope Also migrated 3 orphaned jeff-scoped notebook files to global/ on server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f5388ecc2c
commit
fe031094a4
|
|
@ -423,8 +423,12 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
|||
// ── Sync (via shared runtime) ──
|
||||
|
||||
private async subscribeNotebook(notebookId: string) {
|
||||
this.subscribedDocId = `${this.space}:notes:notebooks:${notebookId}`;
|
||||
const runtime = (window as any).__rspaceOfflineRuntime;
|
||||
// Resolve scope: rnotes is globally-scoped, so use 'global' prefix
|
||||
const dataSpace = runtime?.isInitialized
|
||||
? (runtime.resolveDocSpace?.('rnotes') || this.space)
|
||||
: this.space;
|
||||
this.subscribedDocId = `${dataSpace}:notes:notebooks:${notebookId}`;
|
||||
|
||||
if (runtime?.isInitialized) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import * as Automerge from "@automerge/automerge";
|
|||
import { renderShell } from "../../server/shell";
|
||||
import { getModuleInfoList } from "../../shared/module";
|
||||
import type { RSpaceModule, SpaceLifecycleContext } from "../../shared/module";
|
||||
import { resolveDataSpace } from "../../shared/scope-resolver";
|
||||
import { verifyEncryptIDToken, extractToken } from "@encryptid/sdk/server";
|
||||
import { renderLanding } from "./landing";
|
||||
import { notebookSchema, notebookDocId, connectionsDocId, createNoteItem } from "./schemas";
|
||||
|
|
@ -127,16 +128,19 @@ function findNote(space: string, noteId: string): { docId: string; doc: Notebook
|
|||
function seedDemoIfEmpty(space: string) {
|
||||
if (!_syncServer) return;
|
||||
|
||||
// Resolve effective data space (global for rnotes by default)
|
||||
const dataSpace = resolveDataSpace("rnotes", space);
|
||||
|
||||
// If the space already has notebooks, skip
|
||||
if (listNotebooks(space).length > 0) return;
|
||||
if (listNotebooks(dataSpace).length > 0) return;
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
// Notebook 1: Project Ideas
|
||||
const nb1Id = newId();
|
||||
const nb1DocId = notebookDocId(space, nb1Id);
|
||||
const nb1DocId = notebookDocId(dataSpace, nb1Id);
|
||||
const nb1Doc = Automerge.change(Automerge.init<NotebookDoc>(), "Seed: Project Ideas", (d) => {
|
||||
d.meta = { module: "notes", collection: "notebooks", version: 1, spaceSlug: space, createdAt: now };
|
||||
d.meta = { module: "notes", collection: "notebooks", version: 1, spaceSlug: dataSpace, createdAt: now };
|
||||
d.notebook = { id: nb1Id, title: "Project Ideas", slug: "project-ideas", description: "Brainstorms and design notes for the r* ecosystem", coverColor: "#6366f1", isPublic: true, createdAt: now, updatedAt: now };
|
||||
d.items = {};
|
||||
});
|
||||
|
|
@ -144,9 +148,9 @@ function seedDemoIfEmpty(space: string) {
|
|||
|
||||
// Notebook 2: Meeting Notes
|
||||
const nb2Id = newId();
|
||||
const nb2DocId = notebookDocId(space, nb2Id);
|
||||
const nb2DocId = notebookDocId(dataSpace, nb2Id);
|
||||
const nb2Doc = Automerge.change(Automerge.init<NotebookDoc>(), "Seed: Meeting Notes", (d) => {
|
||||
d.meta = { module: "notes", collection: "notebooks", version: 1, spaceSlug: space, createdAt: now };
|
||||
d.meta = { module: "notes", collection: "notebooks", version: 1, spaceSlug: dataSpace, createdAt: now };
|
||||
d.notebook = { id: nb2Id, title: "Meeting Notes", slug: "meeting-notes", description: "Weekly standups, design reviews, and retrospectives", coverColor: "#f59e0b", isPublic: true, createdAt: now, updatedAt: now };
|
||||
d.items = {};
|
||||
});
|
||||
|
|
@ -154,9 +158,9 @@ function seedDemoIfEmpty(space: string) {
|
|||
|
||||
// Notebook 3: How-To Guides
|
||||
const nb3Id = newId();
|
||||
const nb3DocId = notebookDocId(space, nb3Id);
|
||||
const nb3DocId = notebookDocId(dataSpace, nb3Id);
|
||||
const nb3Doc = Automerge.change(Automerge.init<NotebookDoc>(), "Seed: How-To Guides", (d) => {
|
||||
d.meta = { module: "notes", collection: "notebooks", version: 1, spaceSlug: space, createdAt: now };
|
||||
d.meta = { module: "notes", collection: "notebooks", version: 1, spaceSlug: dataSpace, createdAt: now };
|
||||
d.notebook = { id: nb3Id, title: "How-To Guides", slug: "how-to-guides", description: "Tutorials and onboarding guides for contributors", coverColor: "#10b981", isPublic: true, createdAt: now, updatedAt: now };
|
||||
d.items = {};
|
||||
});
|
||||
|
|
@ -1043,9 +1047,10 @@ export const notesModule: RSpaceModule = {
|
|||
async onSpaceCreate(ctx: SpaceLifecycleContext) {
|
||||
if (!_syncServer) return;
|
||||
|
||||
// Create a default "My Notes" notebook doc for the new space
|
||||
// Create a default "My Notes" notebook doc, using resolved scope
|
||||
const dataSpace = resolveDataSpace("rnotes", ctx.spaceSlug);
|
||||
const notebookId = "default";
|
||||
const docId = notebookDocId(ctx.spaceSlug, notebookId);
|
||||
const docId = notebookDocId(dataSpace, notebookId);
|
||||
|
||||
if (_syncServer.getDoc(docId)) return; // already exists
|
||||
|
||||
|
|
@ -1055,7 +1060,7 @@ export const notesModule: RSpaceModule = {
|
|||
module: "notes",
|
||||
collection: "notebooks",
|
||||
version: 1,
|
||||
spaceSlug: ctx.spaceSlug,
|
||||
spaceSlug: dataSpace,
|
||||
createdAt: Date.now(),
|
||||
};
|
||||
d.notebook = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue