openalmanac 0.2.57 → 0.2.58

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.
@@ -283,8 +283,10 @@ export function registerPageTools(server) {
283
283
  continue;
284
284
  }
285
285
  okCount++;
286
- // Delete local .md and .ref
287
- const published_slug = r.renamed_from ? targetSlugs[results.indexOf(r)] : r.slug;
286
+ // The local file was named with the pre-rename slug. The server returns
287
+ // `renamed_from` on rename so we can clean up the right file without
288
+ // relying on request/response index parity.
289
+ const published_slug = r.renamed_from ?? r.slug;
288
290
  const { filePath, refPath } = resolvePagePaths(published_slug, wiki_slug);
289
291
  try {
290
292
  unlinkSync(filePath);
@@ -119,13 +119,13 @@ export function registerWikiTools(server) {
119
119
  nav: coerceJson(z.array(navItemSchema)).describe("Nav items"),
120
120
  }),
121
121
  async execute({ wiki_slug, nav }) {
122
- // Get current settings, merge nav
123
- const getResp = await request("GET", `/api/w/${wiki_slug}`);
124
- const wiki = (await getResp.json());
125
- const settings = { ...wiki.settings, nav };
122
+ // Single atomic PATCH the backend's update_settings service uses
123
+ // model_dump(exclude_unset=True) to merge partial bodies, so sending
124
+ // only {nav} doesn't touch theme or cover_image_url. Previously this
125
+ // did a GET-then-PATCH, which raced with concurrent settings updates.
126
126
  const resp = await request("PATCH", `/api/w/${wiki_slug}/settings`, {
127
127
  auth: true,
128
- json: settings,
128
+ json: { nav },
129
129
  });
130
130
  return JSON.stringify(await resp.json(), null, 2);
131
131
  },
package/dist/validate.js CHANGED
@@ -2,13 +2,13 @@ import { parse as parseYaml } from "yaml";
2
2
  import { z, ZodError } from "zod";
3
3
  // ── Primitives ──────────────────────────────────────────────────
4
4
  const sourceKeyRe = /^[a-z0-9]+-[a-z0-9]+(-[a-z0-9]+)*$/;
5
- const isoDateRe = /^\d{4}-\d{2}-\d{2}$/;
6
- // YAML can deserialize `accessed_date: 2026-04-17` as a Date object or leave
7
- // it as a string depending on quoting. Backend Pydantic coerces both to a
8
- // `date`; we accept both shapes here.
5
+ // Match pydantic's `date` coercion: a bare YYYY-MM-DD date, OR any ISO-8601
6
+ // datetime prefix pydantic accepts "2026-04-17T00:00:00Z" as a date. yaml
7
+ // may deserialize either as a `Date` object or a string.
8
+ const isoDateLikeRe = /^\d{4}-\d{2}-\d{2}([T ].*)?$/;
9
9
  const accessedDateSchema = z.union([
10
10
  z.date(),
11
- z.string().regex(isoDateRe, "Must be YYYY-MM-DD"),
11
+ z.string().regex(isoDateLikeRe, "Must be YYYY-MM-DD (optionally with an ISO time suffix)"),
12
12
  ]);
13
13
  // ── Source — mirrors backend/src/schemas/source_schemas.py ──────
14
14
  export const sourceSchema = z.object({
@@ -36,6 +36,10 @@ const headerBlockSchema = z.object({
36
36
  // `list` section with ListItem.link.
37
37
  links: z.array(z.string()).default([]),
38
38
  }).strict();
39
+ // Matches `default_factory=HeaderBlock` on the pydantic model. A factory
40
+ // (not a literal) so each default produces a fresh object — preventing
41
+ // shared-reference aliasing if a caller mutates the default.
42
+ const emptyHeader = () => ({ details: [], links: [] });
39
43
  const timelineItemSchema = z.object({
40
44
  primary: z.string(),
41
45
  secondary: z.string().nullable().optional(),
@@ -105,7 +109,7 @@ const sectionSchema = z.discriminatedUnion("type", [
105
109
  keyValueSectionSchema,
106
110
  ]);
107
111
  export const infoboxSchema = z.object({
108
- header: headerBlockSchema.default({ details: [], links: [] }),
112
+ header: headerBlockSchema.default(emptyHeader),
109
113
  sections: z.array(sectionSchema).default([]),
110
114
  }).strict();
111
115
  // ── Frontmatter — mirrors backend PagePublishFrontmatter ────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openalmanac",
3
- "version": "0.2.57",
3
+ "version": "0.2.58",
4
4
  "description": "OpenAlmanac — pull, edit, and push articles to the open knowledge base",
5
5
  "type": "module",
6
6
  "bin": {