Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion e2e/cloud-connection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ test("reviews a scratchpad selectively and collapses outline branches", async ({
result = defaultViewDocuments();
} else if (operation === "execute_view") {
result = defaultViewExecution([]);
} else if (operation === "read" && isViewSourceRead(request.input)) {
result = viewSourceRecord(request.input);
} else if (operation === "read") {
result = scratchpad;
} else result = {};
Expand Down Expand Up @@ -347,6 +349,8 @@ test("acknowledges slow relay creates and prefetches revisions before delete", a
};
records.push(created);
result = valid(created);
} else if (operation === "read" && isViewSourceRead(request.input)) {
result = valid(viewSourceRecord(request.input));
} else if (operation === "read") {
readRequests += 1;
await readGate.promise;
Expand Down Expand Up @@ -505,7 +509,9 @@ test("edits a contract-defined task without collapsing custom status or fields",
result = defaultViewDocuments();
} else if (operation === "execute_view") {
result = defaultViewExecution([record]);
} else if (operation === "read") result = record;
} else if (operation === "read" && isViewSourceRead(request.input))
result = viewSourceRecord(request.input);
else if (operation === "read") result = record;
else if (operation === "update") {
updateInput = request.input as {
patch?: JsonObject;
Expand Down Expand Up @@ -643,6 +649,25 @@ function collectionDescription() {
},
],
},
// A set-up collection also carries the saved-view contracts TaskNotes
// requires; their packs are installed during collection setup.
...bundledManifest.requirements.contracts
.filter((contract) => contract.id !== "tasknotes.task")
.map((contract) => ({
contract_type: "record" as const,
id: contract.id,
version: contract.version,
digest: contract.digest,
schema: { type: "object" },
binding_schema: { type: "object" },
implementations: [] as Array<{
type_name: string;
type_version: number;
digest: string;
fields: Record<string, string>;
binding: JsonObject;
}>,
})),
],
};
}
Expand Down Expand Up @@ -865,6 +890,28 @@ async function fulfillOperation(
});
}

// Saved views are `.base` records read with the ordinary record operation.
function isViewSourceRead(input: unknown): input is { path: string } {
const path = (input as { path?: unknown }).path;
return typeof path === "string" && path.endsWith(".base");
}

function viewSourceRecord({ path }: { path: string }) {
const id = path
.split("/")
.at(-1)!
.replace(/\.base$/u, "");
const name = `${id[0].toUpperCase()}${id.slice(1)}`;
return {
path,
types: ["obsidian_base"],
revision: "view-r1",
frontmatter: { views: [{ type: "tasknotesTaskList", name }] },
body: "",
document: `views:\n - type: tasknotesTaskList\n name: ${name}\n`,
};
}

function defaultViewDocuments() {
return {
views: ["today", "upcoming", "calendar", "projects", "archive"].map(
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
"@fullcalendar/react": "6.1.17",
"@fullcalendar/timegrid": "6.1.17",
"@lezer/highlight": "^1.2.3",
"@mdbase-dev/connect": "0.1.0-beta.114",
"@mdbase-dev/connect-protocol": "0.1.0-beta.114",
"@mdbase-dev/connect": "0.1.0-beta.117",
"@mdbase-dev/connect-protocol": "0.1.0-beta.117",
"@tanstack/react-virtual": "3.14.11",
"@tasknotes/model": "file:vendor/tasknotes-model-0.3.0-rc.15.tgz",
"codemirror": "^6.0.2",
Expand All @@ -86,8 +86,8 @@
"@capacitor/cli": "8.4.2",
"@capacitor/ios": "8.4.2",
"@eslint/js": "10.0.1",
"@mdbase-dev/connect-dev": "0.1.0-beta.114",
"@mdbase-dev/connect-testing": "0.1.0-beta.114",
"@mdbase-dev/connect-dev": "0.1.0-beta.117",
"@mdbase-dev/connect-testing": "0.1.0-beta.117",
"@playwright/test": "1.61.1",
"@testing-library/jest-dom": "7.0.0",
"@testing-library/react": "16.3.2",
Expand All @@ -112,9 +112,9 @@
},
"pnpm": {
"overrides": {
"@mdbase-dev/connect-protocol": "0.1.0-beta.114",
"@mdbase-dev/connect": "0.1.0-beta.114",
"@mdbase-dev/connect-sync": "0.1.0-beta.114"
"@mdbase-dev/connect-protocol": "0.1.0-beta.117",
"@mdbase-dev/connect": "0.1.0-beta.117",
"@mdbase-dev/connect-sync": "0.1.0-beta.117"
},
"patchedDependencies": {}
}
Expand Down
56 changes: 28 additions & 28 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 47 additions & 2 deletions scripts/tasknotes-manifest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { MDBASE_TIMER_FIRED_CONTRACT } from "@mdbase-dev/connect-protocol";
import { loadCanonicalTaskNotesTypePack } from "./canonical-task-pack.mjs";
import { buildScratchpadTypePack } from "./scratchpad-type.mjs";
import { buildScratchImageTypePack } from "./scratch-image-type.mjs";
import { readFile } from "node:fs/promises";
import { resolve } from "node:path";

export { TASKNOTES_APP_TYPE_PACK_VERSION } from "./canonical-task-pack.mjs";

Expand All @@ -15,6 +17,18 @@ export async function buildTaskNotesManifest({
// authorization should use a public tunnel and TASKNOTES_APP_URL.
const identityUrl = appUrl;
const typePack = await loadCanonicalTaskNotesTypePack();
// Saved views are records: Bases through obsidian.base (YAML document
// records) and mdbase views through mdbase.view. The published packs are
// embedded byte for byte.
const viewPack = async (file) =>
JSON.parse(
await readFile(
resolve(process.cwd(), "vendor/mdbase-contracts", file),
"utf8",
),
);
const basePack = await viewPack("obsidian.base-1.0.0.json");
const mdbaseViewPack = await viewPack("mdbase.view-1.0.0.json");
const taskContract = typePack.provides.find(
(contract) => contract.id === "tasknotes.task",
);
Expand All @@ -32,15 +46,18 @@ export async function buildTaskNotesManifest({
],
requirements: {
people: { version: 1, optional: ["identity", "members"] },
contracts: [taskContract],
contracts: [
taskContract,
...basePack.provides,
...mdbaseViewPack.provides,
],
capabilities: {
contract_version: 2,
required: [
"collection.read",
"records.create",
"records.edit",
"records.delete",
"views.manage",
"definitions.manage",
"background.schedule",
],
Expand All @@ -57,13 +74,29 @@ export async function buildTaskNotesManifest({
predicate: "contains",
value: "TaskNotes/Views/**/*.base",
},
// record_extensions is the complete set, so keep Markdown explicitly
// when adding Bases.
{
id: "tasknotes-markdown-records",
path: "/settings/record_extensions",
predicate: "contains",
value: "md",
},
{
id: "tasknotes-base-records",
path: "/settings/record_extensions",
predicate: "contains",
value: "base",
},
],
},
provisions: {
type_packs: [
typePack,
buildScratchpadTypePack(),
buildScratchImageTypePack(),
basePack,
mdbaseViewPack,
],
configuration: [
{
Expand All @@ -72,6 +105,18 @@ export async function buildTaskNotesManifest({
path: "/x-obsidian/bases/include",
value: "TaskNotes/Views/**/*.base",
},
{
requirement: "tasknotes-markdown-records",
operation: "set_add",
path: "/settings/record_extensions",
value: "md",
},
{
requirement: "tasknotes-base-records",
operation: "set_add",
path: "/settings/record_extensions",
value: "base",
},
],
},
notifications: {
Expand Down
27 changes: 26 additions & 1 deletion scripts/tasknotes-manifest.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ describe("TaskNotes mdbase manifest", () => {
version: "0.3.0-rc.5",
digest: expect.stringMatching(/^sha256:[0-9a-f]{64}$/),
}),
expect.objectContaining({ id: "obsidian.base", version: "1.0.0" }),
expect.objectContaining({ id: "mdbase.view", version: "1.0.0" }),
]);
expect(manifest.requirements.files).toEqual({
required: ["list", "read", "add", "replace", "move", "delete"],
Expand All @@ -54,7 +56,6 @@ describe("TaskNotes mdbase manifest", () => {
"records.create",
"records.edit",
"records.delete",
"views.manage",
"definitions.manage",
"background.schedule",
],
Expand All @@ -66,6 +67,18 @@ describe("TaskNotes mdbase manifest", () => {
predicate: "contains",
value: "TaskNotes/Views/**/*.base",
},
{
id: "tasknotes-markdown-records",
path: "/settings/record_extensions",
predicate: "contains",
value: "md",
},
{
id: "tasknotes-base-records",
path: "/settings/record_extensions",
predicate: "contains",
value: "base",
},
]);
expect(manifest.provisions.configuration).toEqual([
{
Expand All @@ -74,6 +87,18 @@ describe("TaskNotes mdbase manifest", () => {
path: "/x-obsidian/bases/include",
value: "TaskNotes/Views/**/*.base",
},
{
requirement: "tasknotes-markdown-records",
operation: "set_add",
path: "/settings/record_extensions",
value: "md",
},
{
requirement: "tasknotes-base-records",
operation: "set_add",
path: "/settings/record_extensions",
value: "base",
},
]);
expect(manifest.provisions.type_packs[0].manifest.resources).toHaveLength(
4,
Expand Down
3 changes: 2 additions & 1 deletion src/cloud/connect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,15 @@ describe("TaskNotes mdbase session", () => {
"update",
"rename",
"delete",
"delete_view_source",
"apply_type_pack",
"reconcile_timers",
"assess_collection_setup",
"apply_collection_setup",
]),
);
expect(expectedOperations).not.toContain("sync");
// Saved views are records written with the record operations.
expect(expectedOperations).not.toContain("delete_view_source");
});

it("evaluates required capabilities through the real SDK without throwing", () => {
Expand Down
Loading
Loading