@glw907/cairn-cms 0.60.0 → 0.62.1
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/CHANGELOG.md +82 -0
- package/dist/components/AdminLayout.svelte +152 -229
- package/dist/components/CairnAdmin.svelte +13 -42
- package/dist/components/CairnLogo.svelte +1 -6
- package/dist/components/CairnMediaLibrary.svelte +821 -1210
- package/dist/components/CairnTidySettings.svelte +194 -261
- package/dist/components/CairnTidySettings.svelte.d.ts +1 -1
- package/dist/components/ComponentForm.svelte +110 -185
- package/dist/components/ComponentInsertDialog.svelte +163 -283
- package/dist/components/ConceptList.svelte +111 -191
- package/dist/components/ConfirmPage.svelte +5 -12
- package/dist/components/CsrfField.svelte +5 -11
- package/dist/components/DeleteDialog.svelte +15 -42
- package/dist/components/EditPage.svelte +781 -1205
- package/dist/components/EditorToolbar.svelte +108 -170
- package/dist/components/HelpHome.svelte +824 -0
- package/dist/components/HelpHome.svelte.d.ts +22 -0
- package/dist/components/IconPicker.svelte +23 -53
- package/dist/components/LinkPicker.svelte +34 -58
- package/dist/components/LoginPage.svelte +14 -27
- package/dist/components/ManageEditors.svelte +3 -15
- package/dist/components/MarkdownEditor.svelte +689 -957
- package/dist/components/MarkdownHelpDialog.svelte +12 -27
- package/dist/components/MediaCaptureCard.svelte +18 -57
- package/dist/components/MediaFigureControl.svelte +32 -71
- package/dist/components/MediaHeroField.svelte +210 -329
- package/dist/components/MediaInsertPopover.svelte +156 -283
- package/dist/components/MediaPicker.svelte +67 -131
- package/dist/components/NavTree.svelte +46 -78
- package/dist/components/RenameDialog.svelte +16 -43
- package/dist/components/ShortcutsDialog.svelte +9 -13
- package/dist/components/ShortcutsGrid.svelte +1 -2
- package/dist/components/TidyReview.svelte +140 -248
- package/dist/components/WebLinkDialog.svelte +19 -40
- package/dist/components/cairn-admin.css +4 -0
- package/dist/components/client-ingest.d.ts +16 -8
- package/dist/components/client-ingest.js +12 -6
- package/dist/components/editor-media.js +16 -8
- package/dist/components/editor-placeholder.d.ts +4 -2
- package/dist/components/editor-tidy.d.ts +24 -12
- package/dist/components/editor-tidy.js +8 -4
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/link-completion.d.ts +12 -6
- package/dist/components/link-completion.js +12 -6
- package/dist/components/markdown-directives.d.ts +9 -6
- package/dist/components/markdown-directives.js +9 -6
- package/dist/components/markdown-format.d.ts +7 -2
- package/dist/components/markdown-format.js +59 -28
- package/dist/components/markdown-reference.d.ts +8 -0
- package/dist/components/markdown-reference.js +22 -0
- package/dist/components/media-upload-outcome.d.ts +12 -6
- package/dist/components/objective-errors.d.ts +8 -4
- package/dist/components/objective-errors.js +8 -4
- package/dist/components/preview-doc.d.ts +4 -2
- package/dist/components/preview-doc.js +4 -2
- package/dist/components/spellcheck.d.ts +57 -29
- package/dist/components/spellcheck.js +50 -20
- package/dist/components/tidy-categorize.d.ts +20 -10
- package/dist/components/tidy-categorize.js +16 -8
- package/dist/components/tidy-validate.d.ts +12 -6
- package/dist/components/tidy-validate.js +20 -10
- package/dist/components/topbar-context.d.ts +4 -2
- package/dist/content/advisories.d.ts +51 -0
- package/dist/content/advisories.js +79 -0
- package/dist/content/compose.d.ts +4 -2
- package/dist/content/compose.js +1 -0
- package/dist/content/excerpt.js +4 -2
- package/dist/content/getting-started.d.ts +18 -0
- package/dist/content/getting-started.js +12 -0
- package/dist/content/links.d.ts +16 -8
- package/dist/content/links.js +12 -6
- package/dist/content/manifest.d.ts +36 -18
- package/dist/content/manifest.js +32 -16
- package/dist/content/media-refs.d.ts +4 -2
- package/dist/content/media-refs.js +4 -2
- package/dist/content/media-rewrite.d.ts +8 -4
- package/dist/content/media-rewrite.js +76 -38
- package/dist/content/schema.d.ts +20 -10
- package/dist/content/site-dictionary.d.ts +4 -2
- package/dist/content/site-dictionary.js +8 -4
- package/dist/content/types.d.ts +97 -42
- package/dist/delivery/CairnHead.svelte +8 -11
- package/dist/delivery/content-index.d.ts +16 -8
- package/dist/delivery/feeds.js +4 -2
- package/dist/delivery/json-ld.d.ts +3 -0
- package/dist/delivery/json-ld.js +3 -0
- package/dist/delivery/manifest.d.ts +4 -2
- package/dist/delivery/manifest.js +4 -2
- package/dist/delivery/public-routes.d.ts +12 -6
- package/dist/delivery/public-routes.js +4 -2
- package/dist/delivery/seo-fields.d.ts +12 -6
- package/dist/delivery/seo-fields.js +8 -4
- package/dist/delivery/site-indexes.d.ts +4 -2
- package/dist/delivery/site-resolver.d.ts +4 -2
- package/dist/delivery/site-resolver.js +4 -2
- package/dist/doctor/cloudflare-api.d.ts +6 -0
- package/dist/doctor/cloudflare-api.js +6 -0
- package/dist/doctor/index.d.ts +12 -6
- package/dist/doctor/report.d.ts +3 -0
- package/dist/doctor/report.js +3 -0
- package/dist/doctor/run.d.ts +3 -0
- package/dist/doctor/run.js +3 -0
- package/dist/doctor/types.d.ts +10 -2
- package/dist/doctor/types.js +6 -0
- package/dist/doctor/wrangler-config.d.ts +7 -2
- package/dist/doctor/wrangler-config.js +3 -0
- package/dist/email.d.ts +4 -2
- package/dist/env.d.ts +0 -3
- package/dist/env.js +0 -3
- package/dist/github/branches.d.ts +4 -2
- package/dist/github/branches.js +4 -2
- package/dist/github/signing.d.ts +1 -1
- package/dist/github/signing.js +2 -2
- package/dist/log/events.d.ts +1 -1
- package/dist/media/bulk-delete-plan.d.ts +8 -4
- package/dist/media/config.d.ts +12 -6
- package/dist/media/config.js +16 -8
- package/dist/media/delivery-bucket.d.ts +4 -2
- package/dist/media/library-entry.d.ts +4 -2
- package/dist/media/library-entry.js +4 -2
- package/dist/media/manifest.d.ts +29 -15
- package/dist/media/manifest.js +29 -16
- package/dist/media/naming.d.ts +12 -6
- package/dist/media/naming.js +24 -12
- package/dist/media/orphan-scan.d.ts +4 -2
- package/dist/media/reconcile.d.ts +21 -11
- package/dist/media/reconcile.js +12 -6
- package/dist/media/reference.d.ts +8 -4
- package/dist/media/reference.js +12 -6
- package/dist/media/rewrite-plan.d.ts +12 -6
- package/dist/media/sniff.d.ts +4 -2
- package/dist/media/sniff.js +28 -14
- package/dist/media/store.d.ts +16 -8
- package/dist/media/store.js +4 -2
- package/dist/media/transform-url.d.ts +12 -6
- package/dist/media/transform-url.js +8 -4
- package/dist/media/usage.d.ts +8 -4
- package/dist/nav/site-config.d.ts +16 -8
- package/dist/render/component-grammar.d.ts +23 -10
- package/dist/render/component-grammar.js +19 -8
- package/dist/render/component-insert.d.ts +8 -4
- package/dist/render/component-insert.js +4 -2
- package/dist/render/component-reference.d.ts +4 -2
- package/dist/render/component-reference.js +4 -2
- package/dist/render/component-validate.d.ts +3 -0
- package/dist/render/component-validate.js +3 -0
- package/dist/render/glyph.d.ts +4 -2
- package/dist/render/glyph.js +4 -2
- package/dist/render/pipeline.d.ts +20 -10
- package/dist/render/pipeline.js +4 -2
- package/dist/render/registry.d.ts +40 -20
- package/dist/render/registry.js +16 -8
- package/dist/render/rehype-dispatch.d.ts +22 -8
- package/dist/render/rehype-dispatch.js +22 -8
- package/dist/render/remark-directives.d.ts +3 -0
- package/dist/render/remark-directives.js +3 -0
- package/dist/render/remark-figure.d.ts +4 -2
- package/dist/render/remark-figure.js +4 -2
- package/dist/render/resolve-links.d.ts +4 -2
- package/dist/render/resolve-links.js +4 -2
- package/dist/render/resolve-media.d.ts +16 -8
- package/dist/render/resolve-media.js +12 -6
- package/dist/sveltekit/admin-dispatch.d.ts +2 -0
- package/dist/sveltekit/admin-dispatch.js +9 -3
- package/dist/sveltekit/auth-routes.d.ts +3 -0
- package/dist/sveltekit/auth-routes.js +3 -0
- package/dist/sveltekit/cairn-admin.d.ts +16 -5
- package/dist/sveltekit/cairn-admin.js +26 -10
- package/dist/sveltekit/content-routes.d.ts +191 -86
- package/dist/sveltekit/content-routes.js +295 -107
- package/dist/sveltekit/editors-routes.d.ts +3 -0
- package/dist/sveltekit/editors-routes.js +3 -0
- package/dist/sveltekit/guard.d.ts +4 -2
- package/dist/sveltekit/guard.js +4 -2
- package/dist/sveltekit/https-required-page.d.ts +1 -1
- package/dist/sveltekit/https-required-page.js +1 -1
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/media-route.d.ts +1 -2
- package/dist/sveltekit/media-route.js +13 -8
- package/dist/sveltekit/nav-routes.d.ts +7 -2
- package/dist/sveltekit/nav-routes.js +3 -0
- package/dist/sveltekit/types.d.ts +4 -2
- package/dist/vite/index.d.ts +32 -16
- package/dist/vite/index.js +52 -26
- package/dist/vite/resolve-root.d.ts +8 -4
- package/dist/vite/resolve-root.js +4 -2
- package/package.json +8 -2
- package/src/lib/components/AdminLayout.svelte +22 -0
- package/src/lib/components/CairnAdmin.svelte +3 -0
- package/src/lib/components/CairnTidySettings.svelte +2 -2
- package/src/lib/components/ComponentForm.svelte +0 -1
- package/src/lib/components/EditPage.svelte +133 -41
- package/src/lib/components/HelpHome.svelte +850 -0
- package/src/lib/components/MarkdownHelpDialog.svelte +4 -15
- package/src/lib/components/client-ingest.ts +20 -10
- package/src/lib/components/editor-media.ts +20 -10
- package/src/lib/components/editor-placeholder.ts +12 -6
- package/src/lib/components/editor-tidy.ts +28 -14
- package/src/lib/components/index.ts +1 -0
- package/src/lib/components/link-completion.ts +12 -6
- package/src/lib/components/markdown-directives.ts +13 -8
- package/src/lib/components/markdown-format.ts +63 -30
- package/src/lib/components/markdown-reference.ts +30 -0
- package/src/lib/components/media-upload-outcome.ts +12 -6
- package/src/lib/components/objective-errors.ts +16 -8
- package/src/lib/components/preview-doc.ts +4 -2
- package/src/lib/components/spellcheck.ts +92 -40
- package/src/lib/components/tidy-categorize.ts +28 -14
- package/src/lib/components/tidy-validate.ts +28 -14
- package/src/lib/components/topbar-context.ts +4 -2
- package/src/lib/content/advisories.ts +141 -0
- package/src/lib/content/compose.ts +5 -2
- package/src/lib/content/excerpt.ts +4 -2
- package/src/lib/content/getting-started.ts +31 -0
- package/src/lib/content/links.ts +16 -8
- package/src/lib/content/manifest.ts +36 -18
- package/src/lib/content/media-refs.ts +4 -2
- package/src/lib/content/media-rewrite.ts +100 -50
- package/src/lib/content/schema.ts +20 -10
- package/src/lib/content/site-dictionary.ts +8 -4
- package/src/lib/content/types.ts +97 -42
- package/src/lib/delivery/content-index.ts +16 -8
- package/src/lib/delivery/feeds.ts +4 -2
- package/src/lib/delivery/json-ld.ts +3 -0
- package/src/lib/delivery/manifest.ts +4 -2
- package/src/lib/delivery/public-routes.ts +16 -8
- package/src/lib/delivery/seo-fields.ts +12 -6
- package/src/lib/delivery/site-indexes.ts +4 -2
- package/src/lib/delivery/site-resolver.ts +4 -2
- package/src/lib/doctor/cloudflare-api.ts +6 -0
- package/src/lib/doctor/index.ts +12 -6
- package/src/lib/doctor/report.ts +3 -0
- package/src/lib/doctor/run.ts +3 -0
- package/src/lib/doctor/types.ts +10 -2
- package/src/lib/doctor/wrangler-config.ts +7 -2
- package/src/lib/email.ts +4 -2
- package/src/lib/env.ts +0 -3
- package/src/lib/github/branches.ts +4 -2
- package/src/lib/github/signing.ts +2 -2
- package/src/lib/log/events.ts +1 -0
- package/src/lib/media/bulk-delete-plan.ts +8 -4
- package/src/lib/media/config.ts +24 -12
- package/src/lib/media/delivery-bucket.ts +4 -2
- package/src/lib/media/library-entry.ts +4 -2
- package/src/lib/media/manifest.ts +33 -18
- package/src/lib/media/naming.ts +24 -12
- package/src/lib/media/orphan-scan.ts +4 -2
- package/src/lib/media/reconcile.ts +21 -11
- package/src/lib/media/reference.ts +12 -6
- package/src/lib/media/rewrite-plan.ts +12 -6
- package/src/lib/media/sniff.ts +28 -14
- package/src/lib/media/store.ts +16 -8
- package/src/lib/media/transform-url.ts +12 -6
- package/src/lib/media/usage.ts +8 -4
- package/src/lib/nav/site-config.ts +16 -8
- package/src/lib/render/component-grammar.ts +23 -10
- package/src/lib/render/component-insert.ts +8 -4
- package/src/lib/render/component-reference.ts +4 -2
- package/src/lib/render/component-validate.ts +3 -0
- package/src/lib/render/glyph.ts +4 -2
- package/src/lib/render/pipeline.ts +20 -10
- package/src/lib/render/registry.ts +44 -22
- package/src/lib/render/rehype-dispatch.ts +22 -8
- package/src/lib/render/remark-directives.ts +3 -0
- package/src/lib/render/remark-figure.ts +4 -2
- package/src/lib/render/resolve-links.ts +4 -2
- package/src/lib/render/resolve-media.ts +16 -8
- package/src/lib/sveltekit/admin-dispatch.ts +10 -4
- package/src/lib/sveltekit/auth-routes.ts +3 -0
- package/src/lib/sveltekit/cairn-admin.ts +37 -15
- package/src/lib/sveltekit/content-routes.ts +492 -197
- package/src/lib/sveltekit/editors-routes.ts +3 -0
- package/src/lib/sveltekit/guard.ts +4 -2
- package/src/lib/sveltekit/https-required-page.ts +1 -1
- package/src/lib/sveltekit/index.ts +3 -0
- package/src/lib/sveltekit/media-route.ts +13 -8
- package/src/lib/sveltekit/nav-routes.ts +7 -2
- package/src/lib/sveltekit/types.ts +4 -2
- package/src/lib/vite/index.ts +60 -30
- package/src/lib/vite/resolve-root.ts +8 -4
|
@@ -5,17 +5,14 @@ tags, and one escaped JSON-LD script. The title renders from seo.title by defaul
|
|
|
5
5
|
lets the site own the <title>, and a string overrides it. It carries no CSS, so it pulls in no
|
|
6
6
|
admin styles.
|
|
7
7
|
-->
|
|
8
|
-
<script lang="ts">
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
title,
|
|
17
|
-
}: { seo: SeoMeta; title?: string | false } = $props();
|
|
18
|
-
const titleText = $derived(title === undefined ? seo.title : title);
|
|
8
|
+
<script lang="ts">import { jsonLdScript } from "./json-ld.js";
|
|
9
|
+
let {
|
|
10
|
+
/** The plain-data head to render. */
|
|
11
|
+
seo,
|
|
12
|
+
/** Title override: a string replaces seo.title, false lets the site own <title>. */
|
|
13
|
+
title
|
|
14
|
+
} = $props();
|
|
15
|
+
const titleText = $derived(title === void 0 ? seo.title : title);
|
|
19
16
|
</script>
|
|
20
17
|
|
|
21
18
|
<svelte:head>
|
|
@@ -6,8 +6,10 @@ export interface RawFile {
|
|
|
6
6
|
}
|
|
7
7
|
/** The cheap, plain-data view of one entry, for lists, feeds, and the sitemap. */
|
|
8
8
|
export interface ContentSummary {
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
9
|
+
/**
|
|
10
|
+
* The descriptor id this entry belongs to, e.g. "posts". Lets a list or page branch per
|
|
11
|
+
* concept without re-deriving it from a proxy like `entry.date`.
|
|
12
|
+
*/
|
|
11
13
|
concept: string;
|
|
12
14
|
id: string;
|
|
13
15
|
slug: string;
|
|
@@ -15,22 +17,28 @@ export interface ContentSummary {
|
|
|
15
17
|
title: string;
|
|
16
18
|
date?: string;
|
|
17
19
|
updated?: string;
|
|
18
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* The entry's tags, always present as an array and empty when the file declares none. This is the
|
|
19
22
|
* read-model normalization. It differs on purpose from the validated `frontmatter.tags`, which the
|
|
20
23
|
* validator omits when empty, so a published file carries no `tags: []` noise. Read `tags` here for
|
|
21
|
-
* a list; read `frontmatter.tags` only when you need the validated, possibly-absent value.
|
|
24
|
+
* a list; read `frontmatter.tags` only when you need the validated, possibly-absent value.
|
|
25
|
+
*/
|
|
22
26
|
tags: string[];
|
|
23
27
|
excerpt: string;
|
|
24
28
|
wordCount: number;
|
|
25
29
|
draft: boolean;
|
|
26
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* The frontmatter keys the descriptor nominated via `summaryFields`, read off the validated,
|
|
27
32
|
* normalized frontmatter. Held in a separate record so a nominated key cannot collide with a
|
|
28
|
-
* typed summary field. Empty when the concept declares no `summaryFields`.
|
|
33
|
+
* typed summary field. Empty when the concept declares no `summaryFields`.
|
|
34
|
+
*/
|
|
29
35
|
fields: Record<string, unknown>;
|
|
30
36
|
}
|
|
31
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* The detail view: a summary plus the frontmatter and the body to render. The frontmatter
|
|
32
39
|
* type defaults to `Record<string, unknown>`; the typed-reads pass infers it from the concept
|
|
33
|
-
* fields. Generic now so that change does not break this signature.
|
|
40
|
+
* fields. Generic now so that change does not break this signature.
|
|
41
|
+
*/
|
|
34
42
|
export interface ContentEntry<F = Record<string, unknown>> extends ContentSummary {
|
|
35
43
|
frontmatter: F;
|
|
36
44
|
body: string;
|
package/dist/delivery/feeds.js
CHANGED
|
@@ -7,8 +7,10 @@ import { escapeXml } from './xml.js';
|
|
|
7
7
|
function cdataSafe(value) {
|
|
8
8
|
return value.replace(/]]>/g, ']]]]><![CDATA[>');
|
|
9
9
|
}
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
10
|
+
/**
|
|
11
|
+
* Parse a YYYY-MM-DD (or ISO) string as a UTC instant. Returns undefined for an absent or
|
|
12
|
+
* unparseable date, so a feed omits the date field rather than emit Invalid Date or throw.
|
|
13
|
+
*/
|
|
12
14
|
function parseFeedDate(date) {
|
|
13
15
|
if (!date)
|
|
14
16
|
return undefined;
|
package/dist/delivery/json-ld.js
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
// The line separator U+2028 and paragraph separator U+2029 get the same treatment: they are
|
|
6
6
|
// legal inside a JSON string but unsafe in inline script text, where some parsers read them as
|
|
7
7
|
// line terminators, so an author pasting one into frontmatter would corrupt the JSON-LD block.
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
8
11
|
export function jsonLdScript(data) {
|
|
9
12
|
const json = JSON.stringify(data)
|
|
10
13
|
.replace(/</g, '\\u003c')
|
|
@@ -2,6 +2,8 @@ import type { Manifest } from '../content/manifest.js';
|
|
|
2
2
|
import type { SiteConfig } from '../nav/site-config.js';
|
|
3
3
|
import type { CairnAdapter } from '../content/types.js';
|
|
4
4
|
import type { SiteGlobs } from './site-indexes.js';
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
5
|
+
/**
|
|
6
|
+
* Build the whole-corpus manifest from a site's adapter, config, and per-concept globs. Drafts are
|
|
7
|
+
* included and flagged, so the admin picker and the guards see the full graph.
|
|
8
|
+
*/
|
|
7
9
|
export declare function buildSiteManifest<A extends CairnAdapter>(adapter: A, config: SiteConfig, globs: SiteGlobs<A>): Manifest;
|
|
@@ -6,8 +6,10 @@ import { siteDescriptors } from './site-descriptors.js';
|
|
|
6
6
|
import { fromGlob } from './content-index.js';
|
|
7
7
|
import { parseMarkdown } from '../content/frontmatter.js';
|
|
8
8
|
import { emptyManifest, manifestEntryFromFile } from '../content/manifest.js';
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
9
|
+
/**
|
|
10
|
+
* Build the whole-corpus manifest from a site's adapter, config, and per-concept globs. Drafts are
|
|
11
|
+
* included and flagged, so the admin picker and the guards see the full graph.
|
|
12
|
+
*/
|
|
11
13
|
export function buildSiteManifest(adapter, config, globs) {
|
|
12
14
|
const globRecord = globs;
|
|
13
15
|
const manifest = emptyManifest();
|
|
@@ -20,12 +20,16 @@ export interface PublicRoutesDeps {
|
|
|
20
20
|
rss?: string;
|
|
21
21
|
json?: string;
|
|
22
22
|
};
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
23
|
+
/**
|
|
24
|
+
* A site-wide default OG image, used when an entry declares none. Resolved to absolute like the
|
|
25
|
+
* canonical URL, so a relative path such as "/og/default.png" works.
|
|
26
|
+
*/
|
|
25
27
|
defaultImage?: string;
|
|
26
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a frontmatter `media:` hero reference to its delivery path. The site builds this from its
|
|
27
30
|
* committed `media.json` exactly as it builds the body resolver (`makeMediaResolver`). When absent,
|
|
28
|
-
* media is off and no `heroImage` projection is derived.
|
|
31
|
+
* media is off and no `heroImage` projection is derived.
|
|
32
|
+
*/
|
|
29
33
|
resolveMedia?: MediaResolve;
|
|
30
34
|
}
|
|
31
35
|
/** The archive and tag list data: summaries the template renders. */
|
|
@@ -52,11 +56,13 @@ export interface EntryData {
|
|
|
52
56
|
seo: SeoMeta;
|
|
53
57
|
newer?: ContentSummary;
|
|
54
58
|
older?: ContentSummary;
|
|
55
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* The resolved hero image, a derived projection of the frontmatter `image` field. `url` is the
|
|
56
61
|
* root-relative delivery path for an `<img>`, `absoluteUrl` the origin-anchored form for the
|
|
57
62
|
* og:image, and `alt`/`caption` carry from the stored object. The canonical token is untouched:
|
|
58
63
|
* `entry.frontmatter.image.src` stays the `media:` token. Undefined when no hero is set, media is
|
|
59
|
-
* off, the reference does not parse, or the resolver finds no asset.
|
|
64
|
+
* off, the reference does not parse, or the resolver finds no asset.
|
|
65
|
+
*/
|
|
60
66
|
heroImage?: {
|
|
61
67
|
url: string;
|
|
62
68
|
absoluteUrl?: string;
|
|
@@ -11,7 +11,8 @@ import { parseMediaToken } from '../media/reference.js';
|
|
|
11
11
|
/** Build the public loaders for a site's unified index. */
|
|
12
12
|
export function createPublicRoutes(deps) {
|
|
13
13
|
const { site, render, origin, siteName, description, feeds, defaultImage, resolveMedia } = deps;
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Derive the hero projection from an entry's frontmatter, without mutating it (locked decision 5).
|
|
15
16
|
* The hero lives at the conventional `image` key as the validated nested object `{ src, alt, caption }`;
|
|
16
17
|
* only an image field's validate arm produces an object-with-string-`src` shape, so detecting that
|
|
17
18
|
* structure is enough (a text field stores a string, a tags field an array). Returns undefined when
|
|
@@ -22,7 +23,8 @@ export function createPublicRoutes(deps) {
|
|
|
22
23
|
* and renders in the editor, but its delivery resolution is not wired here yet, since the field
|
|
23
24
|
* declarations are not reachable in the delivery read path. Honoring a renamed `seo`-flagged field
|
|
24
25
|
* (and a second image field per concept) at delivery is a carried follow-up; every consumer today
|
|
25
|
-
* uses `image`.
|
|
26
|
+
* uses `image`.
|
|
27
|
+
*/
|
|
26
28
|
function deriveHeroImage(frontmatter) {
|
|
27
29
|
if (!resolveMedia)
|
|
28
30
|
return undefined;
|
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The head fields a concept can carry in frontmatter. Each is optional and omitted when absent.
|
|
2
3
|
* `author` is article-scoped downstream: the head builder emits `article:author` only for a dated
|
|
3
|
-
* entry, so an `author` on an undated Page is read here but not rendered.
|
|
4
|
+
* entry, so an `author` on an undated Page is read here but not rendered.
|
|
5
|
+
*/
|
|
4
6
|
export interface SeoFields {
|
|
5
7
|
description?: string;
|
|
6
8
|
image?: string;
|
|
7
9
|
robots?: string;
|
|
8
10
|
author?: string;
|
|
9
11
|
}
|
|
10
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Read the known SEO head fields off an entry's normalized frontmatter. Keeps a present string,
|
|
11
14
|
* trimmed, and omits an absent, empty, or non-string value. Trimming the stored value keeps a stray
|
|
12
15
|
* `robots: " noindex "` from reaching the head tag with surrounding whitespace. The field must be
|
|
13
16
|
* declared in the concept's schema to survive the validate-once read; an undeclared key is not on the
|
|
14
|
-
* normalized frontmatter.
|
|
17
|
+
* normalized frontmatter.
|
|
18
|
+
*/
|
|
15
19
|
export declare function readSeoFields(frontmatter: Record<string, unknown>): SeoFields;
|
|
16
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* Resolve an author-supplied image path to an absolute URL against the site origin. An absolute or
|
|
17
22
|
* protocol-relative URL passes through; a root-relative path anchors to the origin; a malformed
|
|
18
23
|
* string returns undefined rather than throwing at build. The sites use a bare-domain origin, so a
|
|
19
24
|
* bare path also anchors to the origin root; against a sub-path origin it would resolve relative to
|
|
20
|
-
* that path, per the WHATWG URL rules.
|
|
25
|
+
* that path, per the WHATWG URL rules.
|
|
26
|
+
*/
|
|
21
27
|
export declare function resolveImageUrl(image: string, origin: string): string | undefined;
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
// typed Record<string, unknown>; this reads the known head fields by name and coerces. Kept apart
|
|
4
4
|
// from seo.ts (the head builder) so reading frontmatter and building the head stay distinct concerns.
|
|
5
5
|
const KEYS = ['description', 'image', 'robots', 'author'];
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Read the known SEO head fields off an entry's normalized frontmatter. Keeps a present string,
|
|
7
8
|
* trimmed, and omits an absent, empty, or non-string value. Trimming the stored value keeps a stray
|
|
8
9
|
* `robots: " noindex "` from reaching the head tag with surrounding whitespace. The field must be
|
|
9
10
|
* declared in the concept's schema to survive the validate-once read; an undeclared key is not on the
|
|
10
|
-
* normalized frontmatter.
|
|
11
|
+
* normalized frontmatter.
|
|
12
|
+
*/
|
|
11
13
|
export function readSeoFields(frontmatter) {
|
|
12
14
|
const fields = {};
|
|
13
15
|
for (const key of KEYS) {
|
|
@@ -17,11 +19,13 @@ export function readSeoFields(frontmatter) {
|
|
|
17
19
|
}
|
|
18
20
|
return fields;
|
|
19
21
|
}
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Resolve an author-supplied image path to an absolute URL against the site origin. An absolute or
|
|
21
24
|
* protocol-relative URL passes through; a root-relative path anchors to the origin; a malformed
|
|
22
25
|
* string returns undefined rather than throwing at build. The sites use a bare-domain origin, so a
|
|
23
26
|
* bare path also anchors to the origin root; against a sub-path origin it would resolve relative to
|
|
24
|
-
* that path, per the WHATWG URL rules.
|
|
27
|
+
* that path, per the WHATWG URL rules.
|
|
28
|
+
*/
|
|
25
29
|
export function resolveImageUrl(image, origin) {
|
|
26
30
|
try {
|
|
27
31
|
const url = new URL(image, origin);
|
|
@@ -7,8 +7,10 @@ import type { SiteResolver } from './site-resolver.js';
|
|
|
7
7
|
export type SiteGlobs<A extends CairnAdapter> = {
|
|
8
8
|
[K in keyof A['content']]?: Record<string, string>;
|
|
9
9
|
};
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
10
|
+
/**
|
|
11
|
+
* The typed per-concept indexes plus the cross-concept `site` resolver. A concept literally named
|
|
12
|
+
* `site` is not supported, since `site` is the reserved resolver key.
|
|
13
|
+
*/
|
|
12
14
|
export type SiteIndexes<A extends CairnAdapter> = {
|
|
13
15
|
[K in keyof A['content']]: ContentIndex<NonNullable<A['content'][K]> extends ConceptConfig<infer S> ? Infer<S> : Record<string, unknown>>;
|
|
14
16
|
} & {
|
|
@@ -32,6 +32,8 @@ export interface SiteResolver {
|
|
|
32
32
|
export declare function createSiteResolver(concepts: ConceptIndex[], opts?: {
|
|
33
33
|
validate?: boolean;
|
|
34
34
|
}): SiteResolver;
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
35
|
+
/**
|
|
36
|
+
* A resolver backed by the site resolver, for the build. A miss throws, so a dangling cairn: token
|
|
37
|
+
* fails the prerender (the build backstop). The preview uses manifestLinkResolver, which marks.
|
|
38
|
+
*/
|
|
37
39
|
export declare function buildLinkResolver(site: SiteResolver): LinkResolve;
|
|
@@ -60,8 +60,10 @@ export function createSiteResolver(concepts, opts = {}) {
|
|
|
60
60
|
},
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
63
|
+
/**
|
|
64
|
+
* A resolver backed by the site resolver, for the build. A miss throws, so a dangling cairn: token
|
|
65
|
+
* fails the prerender (the build backstop). The preview uses manifestLinkResolver, which marks.
|
|
66
|
+
*/
|
|
65
67
|
export function buildLinkResolver(site) {
|
|
66
68
|
return (ref) => {
|
|
67
69
|
const url = site.concept(ref.concept)?.byId(ref.id)?.permalink;
|
|
@@ -3,5 +3,11 @@ export declare const CF_API = "https://api.cloudflare.com/client/v4";
|
|
|
3
3
|
export declare const NO_TOKEN: CheckResult;
|
|
4
4
|
export declare const NO_FROM: CheckResult;
|
|
5
5
|
export declare const NO_ACCOUNT: CheckResult;
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
6
9
|
export declare function cfGet(ctx: DoctorContext, path: string): Promise<Response>;
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
7
13
|
export declare function cfPost(ctx: DoctorContext, path: string, body: unknown): Promise<Response>;
|
|
@@ -7,11 +7,17 @@ export const CF_API = 'https://api.cloudflare.com/client/v4';
|
|
|
7
7
|
export const NO_TOKEN = skip('set CLOUDFLARE_API_TOKEN to run this check');
|
|
8
8
|
export const NO_FROM = skip('pass --from, set CAIRN_FROM, or configure the cairnManifest plugin so the doctor can read the adapter');
|
|
9
9
|
export const NO_ACCOUNT = skip('set CLOUDFLARE_API_TOKEN, and CLOUDFLARE_ACCOUNT_ID or a wrangler account_id, to run this check');
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
10
13
|
export function cfGet(ctx, path) {
|
|
11
14
|
return ctx.fetch(`${CF_API}${path}`, {
|
|
12
15
|
headers: { authorization: `Bearer ${ctx.cfToken}` },
|
|
13
16
|
});
|
|
14
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
15
21
|
export function cfPost(ctx, path, body) {
|
|
16
22
|
return ctx.fetch(`${CF_API}${path}`, {
|
|
17
23
|
method: 'POST',
|
package/dist/doctor/index.d.ts
CHANGED
|
@@ -5,8 +5,10 @@ export interface DoctorArgs {
|
|
|
5
5
|
from?: string;
|
|
6
6
|
repo?: string;
|
|
7
7
|
sendTest?: string;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
8
|
+
/**
|
|
9
|
+
* The live admin probe: a URL when --probe carried one, true for the bare flag (probe the
|
|
10
|
+
* PUBLIC_ORIGIN input), absent when the flag never appeared (the probe does not run).
|
|
11
|
+
*/
|
|
10
12
|
probe?: string | true;
|
|
11
13
|
}
|
|
12
14
|
/** Parse the bin's argv (long flags only). Throws with a usage line on anything unexpected. */
|
|
@@ -18,12 +20,16 @@ export declare function parseArgs(argv: string[]): DoctorArgs;
|
|
|
18
20
|
* readFile stay with the bin, which injects the real ones.
|
|
19
21
|
*/
|
|
20
22
|
export declare function contextFromEnv(env: Record<string, string | undefined>, args: DoctorArgs, cwd: string): Omit<DoctorContext, 'fetch' | 'readFile'>;
|
|
21
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* The lazy derivation sources the bin wires up: the adapter read through the consumer's own
|
|
22
25
|
* Vite resolution and the wrangler config's account_id. Each runs only when an input it feeds
|
|
23
|
-
* is still missing, so a doctor run with full flags touches neither.
|
|
26
|
+
* is still missing, so a doctor run with full flags touches neither.
|
|
27
|
+
*/
|
|
24
28
|
export interface DerivationSources {
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
29
|
+
/**
|
|
30
|
+
* Returns `{ owner, repo, from, mediaBucketBinding }` off the adapter, or null when nothing is
|
|
31
|
+
* derivable.
|
|
32
|
+
*/
|
|
27
33
|
adapterFacts: () => Promise<{
|
|
28
34
|
owner?: string;
|
|
29
35
|
repo?: string;
|
package/dist/doctor/report.d.ts
CHANGED
package/dist/doctor/report.js
CHANGED
|
@@ -8,6 +8,9 @@ const TAG = {
|
|
|
8
8
|
fail: 'FAIL',
|
|
9
9
|
skip: 'SKIP',
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
11
14
|
export function formatReport(results) {
|
|
12
15
|
const lines = results.map(({ check, result }) => `${TAG[result.status]} ${check.title}: ${result.detail}`);
|
|
13
16
|
const failures = results.filter(({ result }) => result.status === 'fail');
|
package/dist/doctor/run.d.ts
CHANGED
package/dist/doctor/run.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// The doctor's runner: every check executes, every result lands in the table. A throwing check
|
|
2
2
|
// records a fail and the run continues, so one broken probe never hides the rest of the picture.
|
|
3
3
|
import { fail } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
4
7
|
export async function runDoctor(checks, ctx) {
|
|
5
8
|
const results = [];
|
|
6
9
|
let failed = 0;
|
package/dist/doctor/types.d.ts
CHANGED
|
@@ -6,7 +6,13 @@ export interface CheckResult {
|
|
|
6
6
|
}
|
|
7
7
|
/** Result constructors, so a check body reads one outcome per line instead of object literals. */
|
|
8
8
|
export declare function pass(detail: string): CheckResult;
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
*/
|
|
9
12
|
export declare function fail(detail: string): CheckResult;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
10
16
|
export declare function skip(detail: string): CheckResult;
|
|
11
17
|
export interface DoctorCheck {
|
|
12
18
|
/** Stable id, e.g. 'email.sender-onboarded'. */
|
|
@@ -30,8 +36,10 @@ export interface DoctorContext {
|
|
|
30
36
|
cfAccountId?: string;
|
|
31
37
|
/** PUBLIC_ORIGIN, the env fallback when the wrangler vars carry none. */
|
|
32
38
|
publicOrigin?: string;
|
|
33
|
-
/**
|
|
34
|
-
*
|
|
39
|
+
/**
|
|
40
|
+
* The adapter's media bucket binding (cairn.assets.bucketBinding), derived off the adapter.
|
|
41
|
+
* Undefined when the site declares no media assets; the media-bucket check skips in that case.
|
|
42
|
+
*/
|
|
35
43
|
mediaBucketBinding?: string;
|
|
36
44
|
/** GITHUB_APP_ID / GITHUB_APP_INSTALLATION_ID / GITHUB_APP_PRIVATE_KEY_B64. */
|
|
37
45
|
github?: {
|
package/dist/doctor/types.js
CHANGED
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
export function pass(detail) {
|
|
3
3
|
return { status: 'pass', detail };
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
5
8
|
export function fail(detail) {
|
|
6
9
|
return { status: 'fail', detail };
|
|
7
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
8
14
|
export function skip(detail) {
|
|
9
15
|
return { status: 'skip', detail };
|
|
10
16
|
}
|
|
@@ -12,8 +12,13 @@ export interface WranglerFacts {
|
|
|
12
12
|
publicOrigin?: string;
|
|
13
13
|
/** The top-level account_id, when declared; a fallback for CLOUDFLARE_ACCOUNT_ID. */
|
|
14
14
|
accountId?: string;
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
15
|
+
/**
|
|
16
|
+
* The declared r2_buckets binding names; the conditional media check matches the adapter's
|
|
17
|
+
* bucketBinding against this. Not part of the hard config.bindings check (decision 9).
|
|
18
|
+
*/
|
|
17
19
|
r2Buckets: string[];
|
|
18
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
19
24
|
export declare function readWranglerConfig(readFile: DoctorContext['readFile']): Promise<WranglerFacts | null>;
|
package/dist/email.d.ts
CHANGED
|
@@ -15,9 +15,11 @@ export interface AuthBranding {
|
|
|
15
15
|
from: string;
|
|
16
16
|
replyTo?: string;
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The injected send. Production uses `cloudflareSend`; tests pass a sink. A thrown error's
|
|
19
20
|
* text reaches the structured log (scrubbed and truncated), so a custom sender must not embed
|
|
20
|
-
* the message body or the magic link in what it throws.
|
|
21
|
+
* the message body or the magic link in what it throws.
|
|
22
|
+
*/
|
|
21
23
|
export type SendMagicLink = (env: AuthEnv, message: MagicLinkMessage) => Promise<void>;
|
|
22
24
|
/** Build the confirmation email. The link is the only action; the copy stays plain. */
|
|
23
25
|
export declare function buildMagicLinkMessage(input: {
|
package/dist/env.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ import type { DeliveryBucket } from './media/delivery-bucket.js';
|
|
|
5
5
|
*
|
|
6
6
|
* The origin is always config-derived, never read from a request header, so a
|
|
7
7
|
* forged Host header cannot redirect a magic link (spec 7.1, risk H3).
|
|
8
|
-
*
|
|
9
8
|
* @throws CairnError (`config.public-origin-invalid`) when `PUBLIC_ORIGIN` is unset or
|
|
10
9
|
* empty, fails to parse as a URL, or uses http on a non-local host.
|
|
11
10
|
*/
|
|
@@ -17,7 +16,6 @@ export declare function requireOrigin(env: {
|
|
|
17
16
|
*
|
|
18
17
|
* The handlers read D1 off `event.platform.env`; without this a misconfigured binding
|
|
19
18
|
* surfaces as a raw `TypeError` deep in a store call. This gives the failure a name.
|
|
20
|
-
*
|
|
21
19
|
* @throws CairnError (`config.bindings-missing`) when `AUTH_DB` is missing.
|
|
22
20
|
*/
|
|
23
21
|
export declare function requireDb(env: {
|
|
@@ -37,7 +35,6 @@ export declare function requireDb(env: {
|
|
|
37
35
|
* which is truthy but carries no callable `get`. Without that check the cast would succeed and the
|
|
38
36
|
* first `bucket.get(...)` would throw an uncaught 500 rather than the drained 503 a missing binding
|
|
39
37
|
* earns.
|
|
40
|
-
*
|
|
41
38
|
* @throws CairnError (`config.bindings-missing`) when the named binding is absent or not an R2 bucket.
|
|
42
39
|
*/
|
|
43
40
|
export declare function requireBucket(env: Record<string, unknown>, bindingName: string): DeliveryBucket;
|
package/dist/env.js
CHANGED
|
@@ -4,7 +4,6 @@ import { CairnError } from './diagnostics/index.js';
|
|
|
4
4
|
*
|
|
5
5
|
* The origin is always config-derived, never read from a request header, so a
|
|
6
6
|
* forged Host header cannot redirect a magic link (spec 7.1, risk H3).
|
|
7
|
-
*
|
|
8
7
|
* @throws CairnError (`config.public-origin-invalid`) when `PUBLIC_ORIGIN` is unset or
|
|
9
8
|
* empty, fails to parse as a URL, or uses http on a non-local host.
|
|
10
9
|
*/
|
|
@@ -38,7 +37,6 @@ export function requireOrigin(env) {
|
|
|
38
37
|
*
|
|
39
38
|
* The handlers read D1 off `event.platform.env`; without this a misconfigured binding
|
|
40
39
|
* surfaces as a raw `TypeError` deep in a store call. This gives the failure a name.
|
|
41
|
-
*
|
|
42
40
|
* @throws CairnError (`config.bindings-missing`) when `AUTH_DB` is missing.
|
|
43
41
|
*/
|
|
44
42
|
export function requireDb(env) {
|
|
@@ -61,7 +59,6 @@ export function requireDb(env) {
|
|
|
61
59
|
* which is truthy but carries no callable `get`. Without that check the cast would succeed and the
|
|
62
60
|
* first `bucket.get(...)` would throw an uncaught 500 rather than the drained 503 a missing binding
|
|
63
61
|
* earns.
|
|
64
|
-
*
|
|
65
62
|
* @throws CairnError (`config.bindings-missing`) when the named binding is absent or not an R2 bucket.
|
|
66
63
|
*/
|
|
67
64
|
export function requireBucket(env, bindingName) {
|
|
@@ -5,7 +5,9 @@ export declare function branchHeadSha(repo: RepoRef, branch: string, token: stri
|
|
|
5
5
|
export declare function createBranch(repo: RepoRef, branch: string, fromSha: string, token: string): Promise<void>;
|
|
6
6
|
/** Delete `branch`. A 404 (already gone) is success: the desired state holds. */
|
|
7
7
|
export declare function deleteBranch(repo: RepoRef, branch: string, token: string): Promise<void>;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Branch names under `prefix`, sorted. The matching-refs API paginates at 30 by default, so a
|
|
9
10
|
* site with 31+ pending entries would silently truncate; request the 100-per-page maximum and
|
|
10
|
-
* follow the Link rel="next" chain until exhausted.
|
|
11
|
+
* follow the Link rel="next" chain until exhausted.
|
|
12
|
+
*/
|
|
11
13
|
export declare function listBranches(repo: RepoRef, prefix: string, token: string): Promise<string[]>;
|
package/dist/github/branches.js
CHANGED
|
@@ -57,9 +57,11 @@ function nextPageUrl(link) {
|
|
|
57
57
|
}
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
60
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Branch names under `prefix`, sorted. The matching-refs API paginates at 30 by default, so a
|
|
61
62
|
* site with 31+ pending entries would silently truncate; request the 100-per-page maximum and
|
|
62
|
-
* follow the Link rel="next" chain until exhausted.
|
|
63
|
+
* follow the Link rel="next" chain until exhausted.
|
|
64
|
+
*/
|
|
63
65
|
export async function listBranches(repo, prefix, token) {
|
|
64
66
|
const names = [];
|
|
65
67
|
let url = `${gitUrl(repo, `matching-refs/heads/${prefix}`)}?per_page=100`;
|
package/dist/github/signing.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare function installationToken(creds: AppCredentials): Promise<string
|
|
|
7
7
|
* Build an installation-token cache. A module-global instance memoizes the minted token per
|
|
8
8
|
* installation for most of its one-hour life, so a warm Worker isolate reuses it across requests
|
|
9
9
|
* instead of re-signing and re-calling GitHub on every list and commit. A cold isolate re-mints,
|
|
10
|
-
* which is always safe. This mirrors the default of
|
|
10
|
+
* which is always safe. This mirrors the default of `@octokit/auth-app`, which caches installation
|
|
11
11
|
* tokens in memory and returns them until expiry. The TTL stays under GitHub's documented one-hour
|
|
12
12
|
* lifetime, so a fixed margin avoids parsing the API expiry. The cache holds the in-flight
|
|
13
13
|
* promise, not the resolved token, so a cold isolate's parallel loads coalesce into one mint;
|
package/dist/github/signing.js
CHANGED
|
@@ -10,7 +10,7 @@ function bytesToB64url(bytes) {
|
|
|
10
10
|
function buf(bytes) {
|
|
11
11
|
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
12
12
|
}
|
|
13
|
-
/** DER length octets for a value of `n` bytes (short form
|
|
13
|
+
/** DER length octets for a value of `n` bytes (short form `< 128`, else long form). */
|
|
14
14
|
function derLength(n) {
|
|
15
15
|
if (n < 0x80)
|
|
16
16
|
return [n];
|
|
@@ -63,7 +63,7 @@ export async function installationToken(creds) {
|
|
|
63
63
|
* Build an installation-token cache. A module-global instance memoizes the minted token per
|
|
64
64
|
* installation for most of its one-hour life, so a warm Worker isolate reuses it across requests
|
|
65
65
|
* instead of re-signing and re-calling GitHub on every list and commit. A cold isolate re-mints,
|
|
66
|
-
* which is always safe. This mirrors the default of
|
|
66
|
+
* which is always safe. This mirrors the default of `@octokit/auth-app`, which caches installation
|
|
67
67
|
* tokens in memory and returns them until expiry. The TTL stays under GitHub's documented one-hour
|
|
68
68
|
* lifetime, so a fixed margin avoids parsing the API expiry. The cache holds the in-flight
|
|
69
69
|
* promise, not the resolved token, so a cold isolate's parallel loads coalesce into one mint;
|
package/dist/log/events.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type CairnLogEvent = 'auth.link.requested' | 'auth.link.send_failed' | 'auth.token.minted' | 'auth.token.confirmed' | 'auth.session.created' | 'auth.session.destroyed' | 'commit.succeeded' | 'commit.failed' | 'config.invalid' | 'entry.published' | 'entry.discarded' | 'publish.failed' | 'github.unreachable' | 'guard.rejected' | 'media.uploaded' | 'media.upload_failed' | 'media.delivery_failed' | 'media.orphan_reconcile' | 'media.resolve_missing' | 'media.deleted' | 'media.delete_blocked' | 'media.bulk_deleted' | 'media.orphans_purged' | 'media.replaced' | 'media.replace_blocked' | 'media.alt_propagated' | 'dictionary.added' | 'dictionary.add_conflict' | 'tidy.done' | 'tidy.error' | 'tidy.refused' | 'tidy.empty';
|
|
1
|
+
export type CairnLogEvent = 'auth.link.requested' | 'auth.link.send_failed' | 'auth.token.minted' | 'auth.token.confirmed' | 'auth.session.created' | 'auth.session.destroyed' | 'commit.succeeded' | 'commit.failed' | 'config.invalid' | 'entry.published' | 'entry.discarded' | 'publish.failed' | 'publish.address_collision' | 'github.unreachable' | 'guard.rejected' | 'media.uploaded' | 'media.upload_failed' | 'media.delivery_failed' | 'media.orphan_reconcile' | 'media.resolve_missing' | 'media.deleted' | 'media.delete_blocked' | 'media.bulk_deleted' | 'media.orphans_purged' | 'media.replaced' | 'media.replace_blocked' | 'media.alt_propagated' | 'dictionary.added' | 'dictionary.add_conflict' | 'tidy.done' | 'tidy.error' | 'tidy.refused' | 'tidy.empty';
|