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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ wide-screen sequencing and schedule review.

Planner reads and updates these values through the canonical TaskNotes contract;
it does not depend on TaskNotes' application source or a second local task copy.
During authorization, Planner can provision the shared `core-lite` TaskNotes
type pack from `@tasknotes/model`. This lets mdbase bring older collection
definitions up to the required contract digest while preserving an existing
customized task type.

Status and priority choices come from each implementing task type's
`tasknotes.task` binding, including labels, colours, ordering, defaults, and
Expand Down Expand Up @@ -105,7 +109,8 @@ mutated only through `tasknotes.task`. Planner requests only the capabilities
it uses:

- inspect the collection contract
- apply the declared Base-source include setting during authorization
- apply the shared TaskNotes type pack and declared Base-source include setting
during authorization
- query and read TaskNotes records
- watch for collection changes
- update TaskNotes records
Expand Down
69 changes: 68 additions & 1 deletion public/.well-known/mdbase-app.json

Large diffs are not rendered by default.

28 changes: 17 additions & 11 deletions scripts/planner-manifest.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { TASKNOTES_SPEC_VERSION } from "@tasknotes/model";
import { TASKNOTES_CONTRACT_DIGEST } from "@tasknotes/model/mdbase";
import {
buildTaskNotesMdbaseResources,
buildTaskNotesMdbaseTypePack,
} from "@tasknotes/model/mdbase";

export const requiredCapabilities = Object.freeze([
"collection.inspect",
"collection.setup.apply",
"definitions.update",
"definitions.type-pack.apply",
"records.watch",
"records.read",
"records.query",
Expand All @@ -15,11 +19,19 @@ export const requiredCapabilities = Object.freeze([
"views.source.update",
]);

export function buildPlannerManifest({ appUrl, development = false }) {
export async function buildPlannerManifest({ appUrl, development = false }) {
const origin = appUrl.replace(/\/$/, "");
const redirectUris = [`${origin}/auth/mdbase/callback`];
if (development && origin === "http://127.0.0.1:4174")
redirectUris.push("http://localhost:4174/auth/mdbase/callback");
const typePack = await buildTaskNotesMdbaseTypePack(
buildTaskNotesMdbaseResources({ profiles: ["core-lite"] }),
);
const taskContract = typePack.provides.find(
(contract) => contract.id === "tasknotes.task",
);
if (!taskContract)
throw new Error("TaskNotes pack provides no task contract.");
return {
manifest_version: 1,
id: "dev.tasknotes.planner",
Expand All @@ -28,13 +40,7 @@ export function buildPlannerManifest({ appUrl, development = false }) {
icon: `${origin}/tasknotes-mark.svg`,
redirect_uris: redirectUris,
requirements: {
contracts: [
{
id: "tasknotes.task",
version: TASKNOTES_SPEC_VERSION,
digest: TASKNOTES_CONTRACT_DIGEST,
},
],
contracts: [taskContract],
capabilities: {
contract_version: 1,
required: [...requiredCapabilities],
Expand All @@ -50,7 +56,7 @@ export function buildPlannerManifest({ appUrl, development = false }) {
],
},
provisions: {
type_packs: [],
type_packs: [typePack],
configuration: [
{
requirement: "tasknotes-planner-base-sources",
Expand Down
30 changes: 25 additions & 5 deletions scripts/planner-manifest.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { describe, expect, it } from "vitest";
import { buildPlannerManifest } from "./planner-manifest.mjs";

describe("Planner mdbase manifest", () => {
it("keeps production callbacks restricted to the production origin", () => {
const manifest = buildPlannerManifest({
it("keeps production callbacks restricted to the production origin", async () => {
const manifest = await buildPlannerManifest({
appUrl: "https://planner.tasknotes.dev",
});
expect(manifest.homepage).toBe("https://planner.tasknotes.dev/");
Expand All @@ -16,11 +16,31 @@ describe("Planner mdbase manifest", () => {
capabilities: {
required: expect.arrayContaining([
"collection.setup.apply",
"definitions.update",
"definitions.type-pack.apply",
"views.execute",
]),
},
});
expect(manifest.provisions).toMatchObject({ type_packs: [] });
expect(manifest.provisions.type_packs).toHaveLength(1);
expect(manifest.provisions.type_packs[0]).toMatchObject({
manifest: {
id: "tasknotes.task",
resources: expect.arrayContaining([
expect.objectContaining({
kind: "contract",
mode: "managed",
target: "_contracts/tasknotes.task.md",
}),
expect.objectContaining({
kind: "type",
mode: "seed",
target: "_types/task.md",
}),
]),
},
provides: manifest.requirements.contracts,
});
expect(manifest.provisions.configuration).toEqual([
expect.objectContaining({
requirement: "tasknotes-planner-base-sources",
Expand All @@ -29,8 +49,8 @@ describe("Planner mdbase manifest", () => {
]);
});

it("adds both supported loopback callbacks only for development", () => {
const manifest = buildPlannerManifest({
it("adds both supported loopback callbacks only for development", async () => {
const manifest = await buildPlannerManifest({
appUrl: "http://127.0.0.1:4174",
development: true,
});
Expand Down
2 changes: 1 addition & 1 deletion scripts/write-manifest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const development = process.argv.includes("--development");
const appUrl =
process.env.TASKNOTES_PLANNER_URL ??
(development ? "http://127.0.0.1:4174" : "https://planner.tasknotes.dev");
const manifest = buildPlannerManifest({ appUrl, development });
const manifest = await buildPlannerManifest({ appUrl, development });
const serialized = await format(JSON.stringify(manifest), { parser: "json" });
const targets = [
resolve(
Expand Down
69 changes: 68 additions & 1 deletion src/generated-mdbase-app.json

Large diffs are not rendered by default.