hazo_blog 2.16.0 → 2.17.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/CHANGE_LOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes are documented here. This project follows
4
4
  [Semantic Versioning](https://semver.org/).
5
5
 
6
+ ## 2.17.0 — 2026-11-08
7
+
8
+ **Additive — three small cross-tenant/wiring primitives for Phase 1b ticket 15 (SEO verification job).** No DDL. The actual verification job (HTTP checks, HTML parsing, go/no-go evaluation, email alerting) is highly platform-specific (reads the host's own public URLs and its own notification setup) and ships entirely in the BlogSketch platform repo's own commit for this ticket, per this package's usual split — this release only adds the generic primitives that job needed and this package was the only place able to provide correctly.
9
+
10
+ - **`registerBlogMaintenanceJobs` gains `options.extraJobs?: MaintenanceJob[]`** (`src/jobs/maintenance-jobs.ts`) — lets a host wire its OWN `MaintenanceJob`s into the exact same worker/schedule registration as this package's two built-in jobs (auto-publish, purge-trashed), rather than running a second, parallel `hazo_jobs` worker/schedule just to add one more recurring task. Appended after the two built-in jobs, in the given order; omitted/empty is fully back-compat (identical wiring to before this option existed).
11
+ - **`findImportedPosts(adapter, scopeId)`** (`src/repository/posts.ts`, exported from the main entry) — every live (`published`, not soft-deleted) post in one scope whose `custom_fields.__seed_source === "import"`, the one marker a seed-loaded (migrated) post carries. Scoped, unlike `findDueScheduledPosts`/`purgeTrashedPosts` — the verification sweep already knows which `scope_id`s to check (sites with monitoring enabled, a platform-side setting) and checks one at a time.
12
+ - **`listScopesWithSetting(adapter, key)`** (`src/repository/index.ts`, exported from the main entry) — every `scope_id` that has a row for a given plain settings key, across every tenant, with that row's parsed payload. Deliberately generic (not SEO-specific): answers "which sites have this toggle on" for any plain-key settings bridge (same convention as `wp_fallback_enabled`/`contact_email` in the platform repo) without a bespoke cross-tenant query each time. Does NOT degrade-on-error the way `getSetting` does — see its own doc-comment for why a "who do I even check" scan failing silently is the wrong default for a maintenance sweep.
13
+ - Tests: 2 new cases in `src/__tests__/maintenance-jobs.test.ts` (`extraJobs` wired into the same worker/registration; omitted `extraJobs` is unchanged), 4 new cases in `src/__tests__/posts.repository.integration.test.ts` (`findImportedPosts` — scope isolation, excludes draft/trashed/non-import posts), 3 new cases in `src/__tests__/settings.integration.test.ts` (`listScopesWithSetting` — cross-tenant payloads, no rows for an unset key, unaffected by a different key). 9 new tests, all passing; full suite unaffected (same pre-existing, unrelated v1.6/v2.0.0 schema-split failures every release since 2.10.0 has carried — verified unchanged via a scoped `git stash` of just this release's files — zero regressions, +9 passing).
14
+ - **Not done in this release**: the `MaintenanceJob` itself (cron schedule, HTTP checks, HTML parsing, go/no-go evaluation, email alerting, per-site enable/disable + auto-disable settings) — platform repo's own commit, see the BlogSketch platform repo's ticket 15.
15
+
16
+ Bumps 2.16.0 -> 2.17.0 (minor, additive, no DDL).
17
+
6
18
  ## 2.16.0 — 2026-11-08
7
19
 
8
20
  **⚠️ DDL required — site settings + custom CSS data layer (Phase 1b ticket 09): `hazo_blog_site_files`, a typed `SiteIdentity` settings shape, and `RenderSite.ogImage`.** This is the BACKEND/DATA layer — the admin UI, the two API routes, the `RenderContext.site` population, and the `<head>`-injection decision for custom CSS all ship in the BlogSketch platform repo's own commit for this ticket, per this package's usual split (see 2.13.0's menus entry for the same precedent).
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from "./types/index.js";
2
2
  export * from "./lib/index.js";
3
- export { createBlogRepository, type BlogRepository, type RepositoryOptions, type ListQuery, } from "./repository/index.js";
4
- export { createPostRepository, findDueScheduledPosts, purgeTrashedPosts, CategoryNotFoundError, PostConflictError, PostInvalidStatusTransitionError, PostNoDraftRevisionError, PostNoLiveRevisionError, PostNotFoundError, type PostRepository, } from "./repository/posts.js";
3
+ export { createBlogRepository, listScopesWithSetting, type BlogRepository, type RepositoryOptions, type ListQuery, } from "./repository/index.js";
4
+ export { createPostRepository, findDueScheduledPosts, purgeTrashedPosts, findImportedPosts, CategoryNotFoundError, PostConflictError, PostInvalidStatusTransitionError, PostNoDraftRevisionError, PostNoLiveRevisionError, PostNotFoundError, type PostRepository, } from "./repository/posts.js";
5
5
  export { createPostService, resolvePostScope, ScopeUnresolvedError, CustomFieldValidationError, type PostService, } from "./service/posts.js";
6
6
  export { registerSeoHooks } from "./service/seo-hooks.js";
7
7
  export { createBylineRepository, BylineNotFoundError, PostNotFoundForBylineError, type BylineRepository, } from "./repository/bylines.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,8 +6,8 @@ export * from "./types/index.js";
6
6
  // Pure utilities (slug, reading-time, excerpt, toc).
7
7
  export * from "./lib/index.js";
8
8
  // Storage + business logic.
9
- export { createBlogRepository, } from "./repository/index.js";
10
- export { createPostRepository, findDueScheduledPosts, purgeTrashedPosts, CategoryNotFoundError, PostConflictError, PostInvalidStatusTransitionError, PostNoDraftRevisionError, PostNoLiveRevisionError, PostNotFoundError, } from "./repository/posts.js";
9
+ export { createBlogRepository, listScopesWithSetting, } from "./repository/index.js";
10
+ export { createPostRepository, findDueScheduledPosts, purgeTrashedPosts, findImportedPosts, CategoryNotFoundError, PostConflictError, PostInvalidStatusTransitionError, PostNoDraftRevisionError, PostNoLiveRevisionError, PostNotFoundError, } from "./repository/posts.js";
11
11
  export { createPostService, resolvePostScope, ScopeUnresolvedError, CustomFieldValidationError, } from "./service/posts.js";
12
12
  export { registerSeoHooks } from "./service/seo-hooks.js";
13
13
  export { createBylineRepository, BylineNotFoundError, PostNotFoundForBylineError, } from "./repository/bylines.js";
@@ -48,6 +48,20 @@ export interface RegisterBlogMaintenanceJobsOptions {
48
48
  * `better-sqlite3`). Omitted ⇒ falls back to `config.getHazoConnect()`.
49
49
  */
50
50
  rawAdapter?: JobsRawAdapter;
51
+ /**
52
+ * Additional `MaintenanceJob`s to wire into the SAME worker/schedule
53
+ * registration as the two built-in jobs above — added for Phase 1b
54
+ * ticket 15 (SEO verification), whose job is highly platform-specific
55
+ * (HTTP checks against the host's own public URLs, email alerting via
56
+ * the host's own notification setup) and so is defined BY THE HOST, not
57
+ * this package, but still needs the exact same "one recurring schedule
58
+ * per job type, one worker, idempotent on every startup" machinery this
59
+ * function already provides — not a second, parallel scheduling
60
+ * mechanism. Order in the final `types`/registered-jobs array is: the
61
+ * two built-in jobs, then `extraJobs` in the order given. Omitted/empty
62
+ * ⇒ behaviour is identical to before this option existed.
63
+ */
64
+ extraJobs?: MaintenanceJob[];
51
65
  }
52
66
  export interface RegisterBlogMaintenanceJobsDeps {
53
67
  /** Test seam — see the file header. Defaults to a real `import("hazo_jobs/server").catch(() => null)`. */
@@ -1 +1 @@
1
- {"version":3,"file":"maintenance-jobs.d.ts","sourceRoot":"","sources":["../../src/jobs/maintenance-jobs.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,KAAK,gBAAgB,GAAG,cAAc,kBAAkB,CAAC,CAAC;AAC1D,KAAK,cAAc,CAAC,QAAQ,GAAG,OAAO,IAAI,OAAO,WAAW,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;AACvF,+NAA+N;AAC/N,KAAK,cAAc,GAAG;IAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAEvF;;;;;;;;;;;GAWG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAyBrF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAarG;AAED,MAAM,WAAW,kCAAkC;IACjD,8HAA8H;IAC9H,OAAO,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC;IAC1B,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;CAC7B;AAED,MAAM,WAAW,+BAA+B;IAC9C,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CACnD;AAUD,MAAM,WAAW,2BAA2B;IAC1C,qHAAqH;IACrH,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxF;;;;;;;;OAQG;IACH,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,kCAAuC,EAChD,IAAI,GAAE,+BAAoC,GACzC,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAoB7C"}
1
+ {"version":3,"file":"maintenance-jobs.d.ts","sourceRoot":"","sources":["../../src/jobs/maintenance-jobs.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,KAAK,gBAAgB,GAAG,cAAc,kBAAkB,CAAC,CAAC;AAC1D,KAAK,cAAc,CAAC,QAAQ,GAAG,OAAO,IAAI,OAAO,WAAW,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;AACvF,+NAA+N;AAC/N,KAAK,cAAc,GAAG;IAAE,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC;AAEvF;;;;;;;;;;;GAWG;AACH,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAyBrF;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAarG;AAED,MAAM,WAAW,kCAAkC;IACjD,8HAA8H;IAC9H,OAAO,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC;IAC1B,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,+BAA+B;IAC9C,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CACnD;AAUD,MAAM,WAAW,2BAA2B;IAC1C,qHAAqH;IACrH,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxF;;;;;;;;OAQG;IACH,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,kCAAuC,EAChD,IAAI,GAAE,+BAAoC,GACzC,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAwB7C"}
@@ -113,7 +113,11 @@ export async function registerBlogMaintenanceJobs(config, options = {}, deps = {
113
113
  // in variance terms) payload types — register_maintenance_jobs itself only
114
114
  // ever dispatches by `job.type`, so mixing payload shapes in one array is
115
115
  // safe at runtime; this is purely a compile-time widening.
116
- const jobs = [createAutoPublishScheduledPostsJob(config), createPurgeTrashedPostsJob(config)];
116
+ const jobs = [
117
+ createAutoPublishScheduledPostsJob(config),
118
+ createPurgeTrashedPostsJob(config),
119
+ ...(options.extraJobs ?? []),
120
+ ];
117
121
  const worker = client.worker({
118
122
  workerId: options.workerId ?? "hazo-blog-maintenance",
119
123
  types: jobs.map((j) => j.type),
@@ -60,4 +60,29 @@ export interface BlogRepository {
60
60
  settingsTableAvailable(): Promise<boolean>;
61
61
  }
62
62
  export declare function createBlogRepository(adapter: unknown, options?: RepositoryOptions): BlogRepository;
63
+ /**
64
+ * Every `scope_id` that has a row for `key`, across every tenant — added
65
+ * for Phase 1b ticket 15 (SEO verification), whose nightly sweep needs to
66
+ * find "every site with cutover monitoring enabled" WITHOUT already
67
+ * knowing which scopes to check, same reason `findDueScheduledPosts`/
68
+ * `purgeTrashedPosts` (`./posts.js`) scan `hazo_blog_posts` unscoped rather
69
+ * than needing a scope up front. Deliberately generic (not SEO-specific):
70
+ * any plain-key settings bridge (same convention as `wp_fallback_enabled`,
71
+ * `contact_email`, etc. in the BlogSketch platform repo) can use this to
72
+ * answer "which sites have this toggled on" without a bespoke query.
73
+ *
74
+ * Returns the RAW payload for each matching row, parsed the same way
75
+ * `getSetting` parses one (JSON-string or already-object; `null` on a
76
+ * payload that isn't a plain object) — callers decide what a given
77
+ * `payload.value` shape means. Does NOT degrade-on-error the way
78
+ * `getSetting` does: a maintenance sweep that can't read its own
79
+ * "who do I check" list should fail loudly (surfaced as a failed
80
+ * `hazo_jobs` run, logged) rather than silently skipping every site, which
81
+ * is the one case `getSetting`'s single-row "treat a DB hiccup as
82
+ * unconfigured" contract is NOT safe to reuse for.
83
+ */
84
+ export declare function listScopesWithSetting(adapter: unknown, key: string): Promise<Array<{
85
+ scopeId: string;
86
+ payload: Record<string, unknown> | null;
87
+ }>>;
63
88
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repository/index.ts"],"names":[],"mappings":"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"}
@@ -440,3 +440,38 @@ export function createBlogRepository(adapter, options = {}) {
440
440
  },
441
441
  };
442
442
  }
443
+ /**
444
+ * Every `scope_id` that has a row for `key`, across every tenant — added
445
+ * for Phase 1b ticket 15 (SEO verification), whose nightly sweep needs to
446
+ * find "every site with cutover monitoring enabled" WITHOUT already
447
+ * knowing which scopes to check, same reason `findDueScheduledPosts`/
448
+ * `purgeTrashedPosts` (`./posts.js`) scan `hazo_blog_posts` unscoped rather
449
+ * than needing a scope up front. Deliberately generic (not SEO-specific):
450
+ * any plain-key settings bridge (same convention as `wp_fallback_enabled`,
451
+ * `contact_email`, etc. in the BlogSketch platform repo) can use this to
452
+ * answer "which sites have this toggled on" without a bespoke query.
453
+ *
454
+ * Returns the RAW payload for each matching row, parsed the same way
455
+ * `getSetting` parses one (JSON-string or already-object; `null` on a
456
+ * payload that isn't a plain object) — callers decide what a given
457
+ * `payload.value` shape means. Does NOT degrade-on-error the way
458
+ * `getSetting` does: a maintenance sweep that can't read its own
459
+ * "who do I check" list should fail loudly (surfaced as a failed
460
+ * `hazo_jobs` run, logged) rather than silently skipping every site, which
461
+ * is the one case `getSetting`'s single-row "treat a DB hiccup as
462
+ * unconfigured" contract is NOT safe to reuse for.
463
+ */
464
+ export async function listScopesWithSetting(adapter, key) {
465
+ const settings = createCrudService(adapter, SETTINGS);
466
+ const rows = await settings.list(
467
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
468
+ (qb) => qb.where("setting_key", "eq", key));
469
+ return rows.map((row) => {
470
+ const raw = row.payload;
471
+ const parsed = typeof raw === "string" ? safeJsonParse(raw) : raw;
472
+ return {
473
+ scopeId: row.scope_id,
474
+ payload: parsed && typeof parsed === "object" ? parsed : null,
475
+ };
476
+ });
477
+ }
@@ -168,4 +168,22 @@ export declare function findDueScheduledPosts(adapter: unknown, now?: Date): Pro
168
168
  export declare function purgeTrashedPosts(adapter: unknown, olderThanDays?: number, now?: Date): Promise<{
169
169
  purged: number;
170
170
  }>;
171
+ /**
172
+ * Every LIVE (`status: 'published'`, not soft-deleted) post in `scopeId`
173
+ * whose `custom_fields.__seed_source === "import"` — added for Phase 1b
174
+ * ticket 15 (SEO verification). This is the exact, and ONLY, marker a
175
+ * migrated post carries (see `scripts/seed-load-core.ts`'s
176
+ * `importContentItem` in the BlogSketch platform repo: every seed-loaded
177
+ * item is stamped with this plain `custom_fields` key — there is no
178
+ * separate `source`/`origin` column on `hazo_blog_posts`). Scoped to one
179
+ * tenant (unlike `findDueScheduledPosts`/`purgeTrashedPosts` above): the
180
+ * verification sweep already knows which `scope_id`s to check (sites with
181
+ * cutover monitoring enabled, a platform-side setting) and checks one at a
182
+ * time, so there is no cross-tenant query to make here. `custom_fields` is
183
+ * an opaque JSON blob with no portable "equals" operator across both
184
+ * dialects (see `toPost`'s own `parseJsonObject` handling) — filtered in
185
+ * JS, same precedent as `DomainRepository.getPrimaryDomain`'s boolean
186
+ * filter above.
187
+ */
188
+ export declare function findImportedPosts(adapter: unknown, scopeId: string): Promise<Post[]>;
171
189
  //# sourceMappingURL=posts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"posts.d.ts","sourceRoot":"","sources":["../../src/repository/posts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"posts.d.ts","sourceRoot":"","sources":["../../src/repository/posts.ts"],"names":[],"mappings":"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"}
@@ -789,3 +789,30 @@ export async function purgeTrashedPosts(adapter, olderThanDays = 30, now = new D
789
789
  }
790
790
  return { purged: rows.length };
791
791
  }
792
+ /**
793
+ * Every LIVE (`status: 'published'`, not soft-deleted) post in `scopeId`
794
+ * whose `custom_fields.__seed_source === "import"` — added for Phase 1b
795
+ * ticket 15 (SEO verification). This is the exact, and ONLY, marker a
796
+ * migrated post carries (see `scripts/seed-load-core.ts`'s
797
+ * `importContentItem` in the BlogSketch platform repo: every seed-loaded
798
+ * item is stamped with this plain `custom_fields` key — there is no
799
+ * separate `source`/`origin` column on `hazo_blog_posts`). Scoped to one
800
+ * tenant (unlike `findDueScheduledPosts`/`purgeTrashedPosts` above): the
801
+ * verification sweep already knows which `scope_id`s to check (sites with
802
+ * cutover monitoring enabled, a platform-side setting) and checks one at a
803
+ * time, so there is no cross-tenant query to make here. `custom_fields` is
804
+ * an opaque JSON blob with no portable "equals" operator across both
805
+ * dialects (see `toPost`'s own `parseJsonObject` handling) — filtered in
806
+ * JS, same precedent as `DomainRepository.getPrimaryDomain`'s boolean
807
+ * filter above.
808
+ */
809
+ export async function findImportedPosts(adapter, scopeId) {
810
+ const posts = createCrudService(adapter, POSTS);
811
+ const rows = await posts.list(
812
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
813
+ (qb) => qb
814
+ .where("scope_id", "eq", scopeId)
815
+ .where("status", "eq", "published")
816
+ .where("deleted_at", "is", null));
817
+ return rows.map(toPost).filter((post) => post.custom_fields?.__seed_source === "import");
818
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_blog",
3
- "version": "2.16.0",
3
+ "version": "2.17.0",
4
4
  "description": "SEO-optimized blogging package: posts, categories, tags, MDX content, and GA4/GSC/Bing-ready SEO.",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",