@mapled/cli 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/dist/commands.d.ts +2 -1
- package/dist/commands.js +33 -0
- package/dist/index.js +9 -3
- package/dist/md.d.ts +59 -0
- package/dist/md.js +110 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ npx @mapled/cli project link
|
|
|
8
8
|
npx @mapled/cli types generate
|
|
9
9
|
npx @mapled/cli scan --write
|
|
10
10
|
npx @mapled/cli bindings push
|
|
11
|
+
npx @mapled/cli md pull
|
|
11
12
|
npx @mapled/cli doctor
|
|
12
13
|
```
|
|
13
14
|
|
|
@@ -124,6 +125,16 @@ npx @mapled/cli bindings pull
|
|
|
124
125
|
|
|
125
126
|
`bindings pull` writes the pushed manifest into `mapled/manifest.json` — say, after your agent pushed one from a chat and you want the repository's copy. It refuses to overwrite a local file that differs unless you pass `--force`.
|
|
126
127
|
|
|
128
|
+
## Leave a guide for the next agent
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npx @mapled/cli md pull
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Writes `MAPLED.md` at the repository root — the guide Mapled renders from the project for whoever works on the site next, person or AI agent: the project and how the site reads it, the content model with every field's type, rules and help text, where each page renders which field (from the pushed manifest), the last setup run with its verification, the working rules, and the commands that verify the integration. It never contains a secret.
|
|
135
|
+
|
|
136
|
+
The first line is a stamp with the schema hash and the manifest version. Everything below the `<!-- mapled:notes -->` line is yours — conventions, what stays hardcoded on purpose, things to avoid — and survives every `md pull`. A `MAPLED.md` Mapled didn't write is left alone unless you pass `--force`, which moves its content below the notes line. `mapled doctor` tells you when the file no longer matches the project; your AI agent gets the same document from the `get_mapled_md` tool.
|
|
137
|
+
|
|
127
138
|
## Check the integration
|
|
128
139
|
|
|
129
140
|
```bash
|
|
@@ -138,6 +149,7 @@ Mapled doctor — Dolphin Landing
|
|
|
138
149
|
✓ Generated types mapled-types.ts matches the schema (3f9a1c2b4d5e)
|
|
139
150
|
✓ Schema pin mapled/schema.json matches the schema (3f9a1c2b4d5e)
|
|
140
151
|
✓ Site manifest mapled/manifest.json is pushed as manifest v3 (14 bindings on 3 pages)
|
|
152
|
+
✓ MAPLED.md MAPLED.md matches the schema (3f9a1c2b4d5e) and manifest v3
|
|
141
153
|
✓ Environment MAPLED_KEY and MAPLED_WEBHOOK_SECRET in .env.local
|
|
142
154
|
✓ Secrets in git No env files or Mapled secrets are tracked.
|
|
143
155
|
✓ @mapled/next 0.6.0 (current)
|
|
@@ -152,7 +164,7 @@ Mapled doctor — Dolphin Landing
|
|
|
152
164
|
1 warning.
|
|
153
165
|
```
|
|
154
166
|
|
|
155
|
-
The repository side: the link, the sign-in, the generated types, the schema pin, the site manifest (and whether it matches what was pushed), `MAPLED_KEY` and `MAPLED_WEBHOOK_SECRET` in your env files (names only — values are never read out), env files or Mapled secrets tracked by git, the installed `@mapled/next` and CLI versions, the revalidation and preview routes of a Next.js site. The Mapled side, from the same status the AI agent's `check_integration` tool reads: whether the site has read content with the delivery key, the publish webhook and its last delivery, the preview route on the deployed site, the bindings health.
|
|
167
|
+
The repository side: the link, the sign-in, the generated types, the schema pin, the site manifest (and whether it matches what was pushed), `MAPLED.md` (and whether it is what Mapled would render now), `MAPLED_KEY` and `MAPLED_WEBHOOK_SECRET` in your env files (names only — values are never read out), env files or Mapled secrets tracked by git, the installed `@mapled/next` and CLI versions, the revalidation and preview routes of a Next.js site. The Mapled side, from the same status the AI agent's `check_integration` tool reads: whether the site has read content with the delivery key, the publish webhook and its last delivery, the preview route on the deployed site, the bindings health.
|
|
156
168
|
|
|
157
169
|
Exit code 1 when something is marked ✗; `--json` prints the checks for scripts and agents.
|
|
158
170
|
|
|
@@ -171,5 +183,6 @@ Exit code 1 when something is marked ✗; `--json` prints the checks for scripts
|
|
|
171
183
|
| `mapled-types.ts` | `types generate` | TypeScript types of the published content, with `MapledSchema` |
|
|
172
184
|
| `mapled/schema.json` | `schema pull`, `types generate` | The schema this site is built against — `schema diff` starts from it |
|
|
173
185
|
| `mapled/manifest.json` | `scan --write`, `bindings pull`, your agent | Pages and bindings — where the code reads each collection and field |
|
|
186
|
+
| `MAPLED.md` | `md pull`, your agent | The guide for the next agent — project, content model, bindings, working rules; your notes below the marker |
|
|
174
187
|
|
|
175
|
-
Commit all
|
|
188
|
+
Commit all five. Credentials never live in the repository.
|
package/dist/commands.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type ParsedArgs } from "./args.js";
|
|
|
2
2
|
import { type FoundConfig } from "./config.js";
|
|
3
3
|
import { type Connection } from "./credentials.js";
|
|
4
4
|
import { type Fetch } from "./oauth.js";
|
|
5
|
-
/** The commands of waves 1 and 2 (§31). Everything that talks to the
|
|
5
|
+
/** The commands of waves 1 and 2 (§31) and MAPLED.md (§21.3). Everything that talks to the
|
|
6
6
|
world comes in through `Ctx`, so the commands run in tests against a
|
|
7
7
|
fake API and a temp directory. */
|
|
8
8
|
export type Ctx = {
|
|
@@ -28,6 +28,7 @@ export declare function schemaDiff(ctx: Ctx, flags: Flags): Promise<number>;
|
|
|
28
28
|
export declare function manifestValidate(ctx: Ctx, flags: Flags): Promise<number>;
|
|
29
29
|
export declare function bindingsPush(ctx: Ctx, flags: Flags): Promise<void>;
|
|
30
30
|
export declare function bindingsPull(ctx: Ctx, flags: Flags): Promise<void>;
|
|
31
|
+
export declare function mdPull(ctx: Ctx, flags: Flags): Promise<void>;
|
|
31
32
|
export declare function scan(ctx: Ctx, flags: Flags): Promise<void>;
|
|
32
33
|
export declare function doctor(ctx: Ctx, flags: Flags): Promise<number>;
|
|
33
34
|
export {};
|
package/dist/commands.js
CHANGED
|
@@ -10,6 +10,7 @@ import { checkManifest, compareManifests, fileExistsIn, MANIFEST_FILE, manifestS
|
|
|
10
10
|
import { authorize, clientKnown, exchangeCode, registerClient, revokeToken } from "./oauth.js";
|
|
11
11
|
import { formatChecks, GLYPH, paint, summarize, useColor } from "./output.js";
|
|
12
12
|
import { diffSchema, formatChanges, pinSchema, readPin, SCHEMA_FILE, summarizeChanges, writePin } from "./pin.js";
|
|
13
|
+
import { checkMapledMd, MD_FILE, mergeMd } from "./md.js";
|
|
13
14
|
import { loadTypeScript, mergeManifest, scanRepository } from "./scan.js";
|
|
14
15
|
import { generateTypes } from "./types.js";
|
|
15
16
|
/** The OAuth client id for this API — registered once per machine, and
|
|
@@ -367,6 +368,27 @@ export async function bindingsPull(ctx, flags) {
|
|
|
367
368
|
await writeManifestFile(found.dir, stored.manifest);
|
|
368
369
|
ctx.out(`Wrote ${MANIFEST_FILE} from manifest v${stored.version} (pushed ${dr.ago(stored.createdAt)} by ${stored.clientName}) — ${manifestSummary(stored.manifest)}.`);
|
|
369
370
|
}
|
|
371
|
+
/* ---- MAPLED.md ---- */
|
|
372
|
+
export async function mdPull(ctx, flags) {
|
|
373
|
+
const { found, session } = await openSession(ctx, flags);
|
|
374
|
+
const fresh = await session.get("/v1/agent/mapled-md");
|
|
375
|
+
const file = path.join(found.dir, MD_FILE);
|
|
376
|
+
const existing = await readFile(file, "utf8").catch(() => null);
|
|
377
|
+
const merged = mergeMd(fresh.markdown, existing, { force: Boolean(flags.force) });
|
|
378
|
+
if (merged.kind === "unchanged") {
|
|
379
|
+
ctx.out(`${MD_FILE} is up to date (schema ${fresh.schemaHash}).`);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
await writeFile(file, merged.text);
|
|
383
|
+
const c = fresh.counts;
|
|
384
|
+
const summary = `${plural(c.collections, "collection")}, ${plural(c.singles, "single")}, ${plural(c.bindings, "binding")} (schema ${fresh.schemaHash})`;
|
|
385
|
+
if (merged.kind === "created")
|
|
386
|
+
ctx.out(`Wrote ${MD_FILE} — ${summary}. Commit it: the next agent reads it first.`);
|
|
387
|
+
else if (merged.kind === "replaced")
|
|
388
|
+
ctx.out(`Replaced ${MD_FILE} — ${summary}; the previous content was kept below the notes line.`);
|
|
389
|
+
else
|
|
390
|
+
ctx.out(`Updated ${MD_FILE} — ${summary}; the notes below the notes line were kept.`);
|
|
391
|
+
}
|
|
370
392
|
/* ---- wave 2: the scanner ---- */
|
|
371
393
|
function describeScan(result, schema) {
|
|
372
394
|
const singles = new Set(schema.collections.filter((c) => c.kind === "single").map((c) => c.key));
|
|
@@ -478,6 +500,7 @@ export async function doctor(ctx, flags) {
|
|
|
478
500
|
const conn = found ? findConnection(store, api, found.config.project) : undefined;
|
|
479
501
|
let status = null;
|
|
480
502
|
let schema = null;
|
|
503
|
+
let guide = null;
|
|
481
504
|
let authError = null;
|
|
482
505
|
if (conn) {
|
|
483
506
|
const session = new Session(store, ctx.credentialsFile, conn, ctx.fetch);
|
|
@@ -488,6 +511,15 @@ export async function doctor(ctx, flags) {
|
|
|
488
511
|
catch (err) {
|
|
489
512
|
authError = err instanceof Error ? err.message : String(err);
|
|
490
513
|
}
|
|
514
|
+
if (status) {
|
|
515
|
+
// the guide is one more read; an API without it must not fail the sign-in line
|
|
516
|
+
try {
|
|
517
|
+
guide = await session.get("/v1/agent/mapled-md");
|
|
518
|
+
}
|
|
519
|
+
catch {
|
|
520
|
+
guide = "unavailable";
|
|
521
|
+
}
|
|
522
|
+
}
|
|
491
523
|
}
|
|
492
524
|
const checks = [];
|
|
493
525
|
checks.push(dr.checkLink(found ? { path: path.relative(ctx.cwd, found.path) || CONFIG_FILE } : null, status?.project.name ?? conn?.projectName ?? null));
|
|
@@ -510,6 +542,7 @@ export async function doctor(ctx, flags) {
|
|
|
510
542
|
}
|
|
511
543
|
}
|
|
512
544
|
checks.push(dr.checkManifestFile(localManifest ? { manifest: localManifest.manifest, problems: localManifest.problems } : null, remoteManifest));
|
|
545
|
+
checks.push(checkMapledMd(await readFile(path.join(dir, MD_FILE), "utf8").catch(() => null), guide));
|
|
513
546
|
checks.push(dr.checkEnv(await dr.envNames(dir), ctx.env));
|
|
514
547
|
checks.push(dr.checkSecrets(await dr.gitFacts(dir)));
|
|
515
548
|
checks.push(dr.checkSdk(await dr.installedVersion(dir, "@mapled/next"), status?.sdk["@mapled/next"]));
|
package/dist/index.js
CHANGED
|
@@ -3,12 +3,13 @@ import { readFileSync } from "node:fs";
|
|
|
3
3
|
import { createInterface } from "node:readline/promises";
|
|
4
4
|
import { parseArgs } from "./args.js";
|
|
5
5
|
import { openBrowser } from "./browser.js";
|
|
6
|
-
import { bindingsPull, bindingsPush, doctor, generate, link, login, logout, manifestValidate, scan, schemaDiff, schemaPull, } from "./commands.js";
|
|
6
|
+
import { bindingsPull, bindingsPush, doctor, generate, link, login, logout, manifestValidate, mdPull, scan, schemaDiff, schemaPull, } from "./commands.js";
|
|
7
7
|
import { credentialsPath } from "./credentials.js";
|
|
8
8
|
import { CliError } from "./errors.js";
|
|
9
9
|
/** `mapled` — sign in, link a repository to its project, generate types
|
|
10
|
-
for the content, keep the schema pin
|
|
11
|
-
with the code, check the integration (§31, waves 1 and 2
|
|
10
|
+
for the content, keep the schema pin, the site manifest and MAPLED.md
|
|
11
|
+
in step with the code, check the integration (§31, waves 1 and 2;
|
|
12
|
+
§21.3). */
|
|
12
13
|
const HELP = `mapled — the Mapled CLI
|
|
13
14
|
|
|
14
15
|
Usage
|
|
@@ -22,6 +23,7 @@ Usage
|
|
|
22
23
|
mapled manifest validate [--json] Check mapled/manifest.json before pushing it
|
|
23
24
|
mapled bindings push [--dry-run] Push mapled/manifest.json so Mapled grades every binding
|
|
24
25
|
mapled bindings pull [--force] Write the pushed manifest into mapled/manifest.json
|
|
26
|
+
mapled md pull [--force] Write MAPLED.md, the guide for the next agent, from the project
|
|
25
27
|
mapled doctor [--json] Check the integration end to end
|
|
26
28
|
|
|
27
29
|
Options
|
|
@@ -103,6 +105,9 @@ async function main(argv) {
|
|
|
103
105
|
case "bindings pull":
|
|
104
106
|
await bindingsPull(ctx, flags);
|
|
105
107
|
return 0;
|
|
108
|
+
case "md pull":
|
|
109
|
+
await mdPull(ctx, flags);
|
|
110
|
+
return 0;
|
|
106
111
|
case "doctor":
|
|
107
112
|
return doctor(ctx, flags);
|
|
108
113
|
case "auth":
|
|
@@ -111,6 +116,7 @@ async function main(argv) {
|
|
|
111
116
|
case "schema":
|
|
112
117
|
case "manifest":
|
|
113
118
|
case "bindings":
|
|
119
|
+
case "md":
|
|
114
120
|
console.log(HELP);
|
|
115
121
|
return 2;
|
|
116
122
|
default:
|
package/dist/md.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Check } from "./doctor.js";
|
|
2
|
+
/** MAPLED.md (§21.3): Mapled renders the guide for the next agent,
|
|
3
|
+
the repository keeps it. `mapled md pull` writes what
|
|
4
|
+
GET /v1/agent/mapled-md answers and keeps everything below the notes
|
|
5
|
+
marker — that part is the repository's own; `doctor` compares the
|
|
6
|
+
rendered part of the local file with a fresh render. The first line
|
|
7
|
+
is a stamp (`<!-- mapled: project=… schema=… manifest=… generated=… -->`)
|
|
8
|
+
and the only line allowed to differ between a fresh file and an
|
|
9
|
+
up-to-date one. */
|
|
10
|
+
export declare const MD_FILE = "MAPLED.md";
|
|
11
|
+
export declare const NOTES_MARKER = "<!-- mapled:notes -->";
|
|
12
|
+
/** GET /v1/agent/mapled-md */
|
|
13
|
+
export type RenderedMd = {
|
|
14
|
+
file: string;
|
|
15
|
+
notesMarker: string;
|
|
16
|
+
markdown: string;
|
|
17
|
+
schemaHash: string;
|
|
18
|
+
manifestVersion: number | null;
|
|
19
|
+
counts: {
|
|
20
|
+
collections: number;
|
|
21
|
+
singles: number;
|
|
22
|
+
forms: number;
|
|
23
|
+
bindings: number;
|
|
24
|
+
pages: number;
|
|
25
|
+
};
|
|
26
|
+
generatedAt: string;
|
|
27
|
+
};
|
|
28
|
+
export type MdStamp = {
|
|
29
|
+
project: string | null;
|
|
30
|
+
schema: string | null;
|
|
31
|
+
manifest: string | null;
|
|
32
|
+
};
|
|
33
|
+
export type MdParts = {
|
|
34
|
+
stamp: MdStamp;
|
|
35
|
+
/** the stamp line as written */
|
|
36
|
+
stampLine: string;
|
|
37
|
+
/** everything between the stamp and the notes marker */
|
|
38
|
+
body: string;
|
|
39
|
+
/** everything after the marker line; null when the file has no marker */
|
|
40
|
+
notes: string | null;
|
|
41
|
+
};
|
|
42
|
+
/** Splits a MAPLED.md written by Mapled; null for any other file. */
|
|
43
|
+
export declare function splitMd(text: string): MdParts | null;
|
|
44
|
+
export type MergedMd = {
|
|
45
|
+
kind: "unchanged";
|
|
46
|
+
} | {
|
|
47
|
+
kind: "created" | "updated" | "replaced";
|
|
48
|
+
text: string;
|
|
49
|
+
};
|
|
50
|
+
/** The file to write: the fresh render, with the repository's notes kept.
|
|
51
|
+
A file Mapled did not write is left alone unless forced — then its
|
|
52
|
+
whole content moves below the notes line, so nothing is lost. */
|
|
53
|
+
export declare function mergeMd(fresh: string, existing: string | null, opts?: {
|
|
54
|
+
force?: boolean;
|
|
55
|
+
}): MergedMd;
|
|
56
|
+
/** `doctor`'s line: is the repository's guide what Mapled would render now?
|
|
57
|
+
`fresh` is null without a sign-in and "unavailable" when Mapled
|
|
58
|
+
answered the other calls but not this one (an API without the route). */
|
|
59
|
+
export declare function checkMapledMd(local: string | null, fresh: RenderedMd | null | "unavailable"): Check;
|
package/dist/md.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { CliError } from "./errors.js";
|
|
2
|
+
/** MAPLED.md (§21.3): Mapled renders the guide for the next agent,
|
|
3
|
+
the repository keeps it. `mapled md pull` writes what
|
|
4
|
+
GET /v1/agent/mapled-md answers and keeps everything below the notes
|
|
5
|
+
marker — that part is the repository's own; `doctor` compares the
|
|
6
|
+
rendered part of the local file with a fresh render. The first line
|
|
7
|
+
is a stamp (`<!-- mapled: project=… schema=… manifest=… generated=… -->`)
|
|
8
|
+
and the only line allowed to differ between a fresh file and an
|
|
9
|
+
up-to-date one. */
|
|
10
|
+
export const MD_FILE = "MAPLED.md";
|
|
11
|
+
export const NOTES_MARKER = "<!-- mapled:notes -->";
|
|
12
|
+
/** Splits a MAPLED.md written by Mapled; null for any other file. */
|
|
13
|
+
export function splitMd(text) {
|
|
14
|
+
const lines = text.split("\n");
|
|
15
|
+
const first = lines[0] ?? "";
|
|
16
|
+
const m = /^<!-- mapled: (.*) -->\s*$/.exec(first);
|
|
17
|
+
if (!m)
|
|
18
|
+
return null;
|
|
19
|
+
const stamp = { project: null, schema: null, manifest: null };
|
|
20
|
+
for (const pair of m[1].split(/\s+/)) {
|
|
21
|
+
const eq = pair.indexOf("=");
|
|
22
|
+
if (eq === -1)
|
|
23
|
+
continue;
|
|
24
|
+
const key = pair.slice(0, eq);
|
|
25
|
+
const value = pair.slice(eq + 1);
|
|
26
|
+
if (key === "project" || key === "schema" || key === "manifest")
|
|
27
|
+
stamp[key] = value;
|
|
28
|
+
}
|
|
29
|
+
const marker = lines.indexOf(NOTES_MARKER, 1);
|
|
30
|
+
const body = lines.slice(1, marker === -1 ? lines.length : marker).join("\n");
|
|
31
|
+
const notes = marker === -1 ? null : lines.slice(marker + 1).join("\n");
|
|
32
|
+
return { stamp, stampLine: first, body, notes };
|
|
33
|
+
}
|
|
34
|
+
/** The same render: the body and what the stamp says about it, never
|
|
35
|
+
the time it was rendered at. */
|
|
36
|
+
function sameRender(a, b) {
|
|
37
|
+
return a.body === b.body && a.stamp.schema === b.stamp.schema && a.stamp.manifest === b.stamp.manifest;
|
|
38
|
+
}
|
|
39
|
+
/** The file to write: the fresh render, with the repository's notes kept.
|
|
40
|
+
A file Mapled did not write is left alone unless forced — then its
|
|
41
|
+
whole content moves below the notes line, so nothing is lost. */
|
|
42
|
+
export function mergeMd(fresh, existing, opts = {}) {
|
|
43
|
+
const next = splitMd(fresh);
|
|
44
|
+
if (!next || next.notes === null)
|
|
45
|
+
throw new CliError("Mapled answered a guide without its stamp or notes marker — update @mapled/cli and try again.");
|
|
46
|
+
if (existing === null)
|
|
47
|
+
return { kind: "created", text: fresh };
|
|
48
|
+
const current = splitMd(existing);
|
|
49
|
+
if (!current) {
|
|
50
|
+
if (!opts.force) {
|
|
51
|
+
throw new CliError(`${MD_FILE} here wasn't written by Mapled. Pass --force to replace it — the current content moves below the notes line, nothing is lost.`);
|
|
52
|
+
}
|
|
53
|
+
const kept = existing.replace(/\s+$/, "");
|
|
54
|
+
return { kind: "replaced", text: `${next.stampLine}\n${next.body}\n${NOTES_MARKER}\n## Notes\n\n${kept}\n` };
|
|
55
|
+
}
|
|
56
|
+
if (sameRender(current, next) && current.notes !== null)
|
|
57
|
+
return { kind: "unchanged" };
|
|
58
|
+
const notes = current.notes === null || current.notes.trim() === "" ? next.notes : current.notes;
|
|
59
|
+
return { kind: "updated", text: `${next.stampLine}\n${next.body}\n${NOTES_MARKER}\n${notes}` };
|
|
60
|
+
}
|
|
61
|
+
/** `doctor`'s line: is the repository's guide what Mapled would render now?
|
|
62
|
+
`fresh` is null without a sign-in and "unavailable" when Mapled
|
|
63
|
+
answered the other calls but not this one (an API without the route). */
|
|
64
|
+
export function checkMapledMd(local, fresh) {
|
|
65
|
+
const label = "MAPLED.md";
|
|
66
|
+
if (local === null) {
|
|
67
|
+
return { key: "mapled_md", label, status: "skipped", detail: `No ${MD_FILE} — run \`mapled md pull\` so the next agent starts from the current integration.` };
|
|
68
|
+
}
|
|
69
|
+
if (fresh === null)
|
|
70
|
+
return { key: "mapled_md", label, status: "skipped", detail: "Sign in to compare with Mapled." };
|
|
71
|
+
if (fresh === "unavailable") {
|
|
72
|
+
return { key: "mapled_md", label, status: "skipped", detail: "Mapled didn't answer with a guide — update @mapled/cli, or try again later." };
|
|
73
|
+
}
|
|
74
|
+
const current = splitMd(local);
|
|
75
|
+
if (!current) {
|
|
76
|
+
return {
|
|
77
|
+
key: "mapled_md",
|
|
78
|
+
label,
|
|
79
|
+
status: "warning",
|
|
80
|
+
detail: `${MD_FILE} wasn't written by Mapled — run \`mapled md pull --force\` to replace it (the current content moves below the notes line).`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
const next = splitMd(fresh.markdown);
|
|
84
|
+
const manifest = fresh.manifestVersion === null ? "none" : `v${fresh.manifestVersion}`;
|
|
85
|
+
if (next && sameRender(current, next) && current.notes !== null) {
|
|
86
|
+
return {
|
|
87
|
+
key: "mapled_md",
|
|
88
|
+
label,
|
|
89
|
+
status: "passed",
|
|
90
|
+
detail: `${MD_FILE} matches the schema (${fresh.schemaHash})${fresh.manifestVersion === null ? "" : ` and manifest ${manifest}`}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (current.stamp.schema && current.stamp.schema !== fresh.schemaHash) {
|
|
94
|
+
return {
|
|
95
|
+
key: "mapled_md",
|
|
96
|
+
label,
|
|
97
|
+
status: "warning",
|
|
98
|
+
detail: `${MD_FILE} describes schema ${current.stamp.schema}; the schema is ${fresh.schemaHash} — run \`mapled md pull\`.`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (current.stamp.manifest && current.stamp.manifest !== manifest) {
|
|
102
|
+
return {
|
|
103
|
+
key: "mapled_md",
|
|
104
|
+
label,
|
|
105
|
+
status: "warning",
|
|
106
|
+
detail: `${MD_FILE} describes manifest ${current.stamp.manifest}; ${manifest === "none" ? "none is pushed now" : `${manifest} is pushed`} — run \`mapled md pull\`.`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return { key: "mapled_md", label, status: "warning", detail: `${MD_FILE} is out of date — run \`mapled md pull\`.` };
|
|
110
|
+
}
|
package/package.json
CHANGED