@fern-api/fdr-sdk 1.2.165-800b1938f3 → 1.2.166-e8ae898b4d

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.
@@ -0,0 +1,80 @@
1
+ import type { LedgerManifest, LedgerSiblingSite } from "../orpc-client/index.js";
2
+ import type { TransformResult } from "./docsPublishTransform.js";
3
+ import type { ArtifactInput, InlineTranslationParams, PublishParams } from "./inputTypes.js";
4
+ export interface BuildLedgerManifestArgs {
5
+ /** Base-locale entities + deployment/site identity (canonical fern URL). */
6
+ params: PublishParams;
7
+ /** Base-locale transform result (carries config + file dimensions). */
8
+ baseResult: TransformResult;
9
+ /** Additional-locale entities, persisted in the same deployment. */
10
+ inlineTranslations: InlineTranslationParams[];
11
+ /**
12
+ * pageId → bare `fullPath`s of the files each page embeds, merged across all
13
+ * locales (ADR 0016, "File metadata on the render path"). Used to pack each
14
+ * route shard's `files` identity map and to prune the relocated files from
15
+ * the pointer's global `files` map. Empty ⇒ no shard-side files; the pointer
16
+ * keeps every file (graceful when the publishing CLI predates the field).
17
+ */
18
+ referencedFilesByPageId: Record<string, string[]>;
19
+ deploymentId: string;
20
+ siteId: string;
21
+ deploymentHash: string;
22
+ orgId: string;
23
+ /** Canonical fern domain (the per-URL manifest is written once per URL by the caller). */
24
+ domain: string;
25
+ /**
26
+ * Domain used for file anchoring (S3 keys + manifest `files[].domain`).
27
+ * When set, overrides `params.site.domain` so preview publishes anchor
28
+ * files on the canonical production domain (ADR 0010).
29
+ */
30
+ fileDomain?: string;
31
+ basepath: string;
32
+ isPreview: boolean;
33
+ isPrivate: boolean;
34
+ /** FAI Ask AI enablement for this URL; omitted when it could not be resolved. */
35
+ askAiEnabled?: boolean;
36
+ /** Live sites on this host; only for basepath-aware production publishes. */
37
+ siblingSites?: LedgerSiblingSite[];
38
+ /** ISO-8601 — request time the publish became live. */
39
+ assignedAt: string;
40
+ assignedBy: string | null;
41
+ /** artifact hash → ISO-8601 `created_at` from `docs_ledger_artifacts`. */
42
+ artifactHashToCreatedAt?: Map<string, string>;
43
+ }
44
+ export interface LedgerReadModelBlob {
45
+ hash: string;
46
+ bytes: Buffer;
47
+ contentType: string;
48
+ }
49
+ export interface BuildLedgerReadModelResult {
50
+ pointer: LedgerManifest;
51
+ blobs: LedgerReadModelBlob[];
52
+ }
53
+ /**
54
+ * Overlay CAS content `created_at` onto the artifact-keyed `createdAt` map
55
+ * used for manifest route entries (sitemap `<lastmod>`). Artifact hashes are
56
+ * salted with `FDR_VERSION`, so their rows are re-minted on the first publish
57
+ * after every FDR deploy; the unsalted content row survives deploys and
58
+ * reflects when the page bytes first appeared. Content-less artifacts (links,
59
+ * files) keep the artifact row's timestamp.
60
+ */
61
+ export declare function overlayContentCreatedAt({ artifacts, artifactHashToCreatedAt, contentHashToCreatedAt }: {
62
+ artifacts: ReadonlyArray<Pick<ArtifactInput, "hash" | "contentHash">>;
63
+ artifactHashToCreatedAt: ReadonlyMap<string, string>;
64
+ contentHashToCreatedAt: ReadonlyMap<string, string>;
65
+ }): Map<string, string>;
66
+ /**
67
+ * Assemble the pointer + immutable CAS read model (ADR 0016) from the
68
+ * in-memory transform result the DAO just persisted. No DB read-back: every
69
+ * field comes from `params` / `baseResult` / `inlineTranslations`, and segment /
70
+ * artifact ids are content hashes (the S3-only reader never correlates against
71
+ * postgres).
72
+ *
73
+ * Leaf content (page markdown, API definitions) is referenced by CAS hash only
74
+ * — the bundle fetches those blobs directly. Hot-path chrome text
75
+ * (header/footer/css.inline/js.inline) is re-inlined into the pointer so page
76
+ * renders do not pay extra CAS reads for site chrome.
77
+ */
78
+ export declare function buildLedgerReadModel(args: BuildLedgerManifestArgs): BuildLedgerReadModelResult;
79
+ export declare function buildLedgerManifest(args: BuildLedgerManifestArgs): LedgerManifest;
80
+ //# sourceMappingURL=buildLedgerManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildLedgerManifest.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/buildLedgerManifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAMR,cAAc,EAKd,iBAAiB,EAUpB,MAAM,yBAAyB,CAAC;AAWjC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EACR,aAAa,EACb,uBAAuB,EACvB,aAAa,EAGhB,MAAM,iBAAiB,CAAC;AA8JzB,MAAM,WAAW,uBAAuB;IACpC,4EAA4E;IAC5E,MAAM,EAAE,aAAa,CAAC;IACtB,uEAAuE;IACvE,UAAU,EAAE,eAAe,CAAC;IAC5B,oEAAoE;IACpE,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;IAC9C;;;;;;OAMG;IACH,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACnC,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0EAA0E;IAC1E,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,0BAA0B;IACvC,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,mBAAmB,EAAE,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,EACpC,SAAS,EACT,uBAAuB,EACvB,sBAAsB,EACzB,EAAE;IACC,SAAS,EAAE,aAAa,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC;IACtE,uBAAuB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvD,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAYtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,uBAAuB,GAAG,0BAA0B,CA2uB9F;AA0CD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,cAAc,CAEjF"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Deterministic hash computation for docs-ledger entities.
3
+ *
4
+ * Server-internal — these functions are NOT shared with the client.
5
+ * The server is the sole authority for structural hash computation.
6
+ *
7
+ * All hashes use SHA-256 over {@link stableStringify}, which produces
8
+ * deterministic JSON by sorting object keys during serialization.
9
+ * `JSON.stringify`'s replacer runs after `toJSON()`, so Dates and custom
10
+ * serializers are handled by the engine — no special cases needed.
11
+ */
12
+ import type { DocsPublishInput, LedgerSegmentDetailMetadata, LedgerSegmentMetadata } from "../orpc-client/index.js";
13
+ export { stableStringify } from "./stableHash.js";
14
+ /**
15
+ * The FDR release version, injected as an env var by the CDK deploy stack.
16
+ * Included in deployment, segment, and artifact hashes so that every FDR
17
+ * deploy invalidates cached structural rows — even when the publish input
18
+ * is byte-identical.
19
+ *
20
+ * Falls back to "local" for local development (where no env var is set),
21
+ * ensuring hashes are still deterministic within a single server instance.
22
+ */
23
+ export declare const FDR_VERSION: string;
24
+ /**
25
+ * Compute the deployment hash directly from the publish input.
26
+ *
27
+ * Since the server-side transform is deterministic, identical inputs always
28
+ * produce identical deployments. This lets us:
29
+ * - Return a real deployment hash from register (before the transform runs)
30
+ * - Short-circuit finish when the deployment hash matches the current one
31
+ *
32
+ * The hash covers everything that affects the deployment's content:
33
+ * nav tree, page content hashes, API manifest hash, global blob hashes, locale,
34
+ * and the {@link FDR_VERSION} salt.
35
+ */
36
+ export declare function hashDeploymentInput(input: DocsPublishInput): string;
37
+ export interface SegmentDetailHashInput {
38
+ type: string;
39
+ displayName: string;
40
+ icon?: string | null;
41
+ sortOrder: number;
42
+ metadata: LedgerSegmentDetailMetadata;
43
+ hidden: boolean;
44
+ viewers: string[];
45
+ orphaned: boolean;
46
+ featureFlags: string[];
47
+ }
48
+ export declare function hashSegmentDetail(input: SegmentDetailHashInput): string;
49
+ export interface ArtifactHashInput {
50
+ type: string;
51
+ hidden: boolean;
52
+ metadata: Record<string, unknown>;
53
+ /** CAS content hash. Null for content-less artifacts (links). */
54
+ contentHash: string | null;
55
+ }
56
+ export declare function hashArtifact(input: ArtifactHashInput): string;
57
+ export interface SegmentHashInput {
58
+ locale: string;
59
+ productHash?: string;
60
+ versionHash?: string;
61
+ variantHash?: string;
62
+ tabHash?: string;
63
+ section: string;
64
+ metadata: LedgerSegmentMetadata;
65
+ hidden: boolean;
66
+ /** Artifact hashes included in this segment — sorted internally for determinism. */
67
+ artifactHashes: string[];
68
+ /** Sidebar ordering: artifact hash + display position. Sorted by displaySortOrder for determinism. */
69
+ displaySortOrder: Array<{
70
+ artifactHash: string;
71
+ displaySortOrder: number;
72
+ }>;
73
+ /** Route entries — sorted by fullPath internally for determinism. */
74
+ routes: Array<{
75
+ fullPath: string;
76
+ artifactHash: string;
77
+ }>;
78
+ }
79
+ export declare function hashSegment(input: SegmentHashInput): string;
80
+ //# sourceMappingURL=docsLedgerHash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docsLedgerHash.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/docsLedgerHash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAIpH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAUlD;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,MAA2C,CAAC;AAEtE;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAOnE;AAuCD,MAAM,WAAW,sBAAsB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,2BAA2B,CAAC;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,CAavE;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,iEAAiE;IACjE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAE7D;AAED,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,oFAAoF;IACpF,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,sGAAsG;IACtG,gBAAgB,EAAE,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,qEAAqE;IACrE,MAAM,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAyB3D"}
@@ -0,0 +1,178 @@
1
+ import type { ApiDefinition } from "../api-definition/index.js";
2
+ import type { BlobRef, LedgerConfig, LocaleEntry } from "../orpc-client/index.js";
3
+ import type { ArtifactInput, DeploymentApiDefinitionInput, DeploymentSegmentInput, DocsSiteProduct, NavInput, SegmentDetailInput, SegmentInput } from "./inputTypes.js";
4
+ /**
5
+ * Input type for `transformPublishInput`. A single locale's content fields
6
+ * plus the deployment-scoped `domain` (needed for file-artifact S3 key
7
+ * construction).
8
+ */
9
+ export type TransformInput = LocaleEntry & {
10
+ domain: string;
11
+ /**
12
+ * Override for the file-anchoring domain (S3 keys). When set, files
13
+ * are keyed under this domain instead of `domain`, so preview
14
+ * publishes can anchor on the canonical fern domain (ADR 0010).
15
+ */
16
+ fileDomain?: string;
17
+ };
18
+ /**
19
+ * A fileManifest entry collected during the transform. Carries everything
20
+ * the register/finish handlers need to route uploads to the correct S3
21
+ * bucket and upsert `docs_ledger_file` rows. The asset domain is the
22
+ * canonical `DocsPublishInput.domain`; custom domains share that namespace.
23
+ * The bucket is determined by the handler (not the transform) from the
24
+ * site's auth config.
25
+ */
26
+ export interface TransformFileEntry {
27
+ fullPath: string;
28
+ hash: string;
29
+ contentType: string;
30
+ contentLength: number;
31
+ filename: string;
32
+ width?: number;
33
+ height?: number;
34
+ blurDataURL?: string;
35
+ }
36
+ /**
37
+ * Parsed API manifest: full API definitions keyed by apiDefinitionId.
38
+ * The finish handler fetches the manifest blob from S3 and parses it.
39
+ */
40
+ export type ApiManifest = Record<string, ApiDefinition>;
41
+ /**
42
+ * A BlobRef whose bytes were generated server-side (pruned API content, link metadata).
43
+ * The router must upload these to CAS before persisting the deployment.
44
+ */
45
+ export interface GeneratedBlob {
46
+ ref: BlobRef;
47
+ bytes: Buffer;
48
+ }
49
+ /**
50
+ * Transform result: hashed entities ready for the DAO, plus content
51
+ * references and server-generated blobs for CAS upload.
52
+ */
53
+ export interface TransformResult {
54
+ segmentDetails: SegmentDetailInput[];
55
+ artifacts: ArtifactInput[];
56
+ segments: SegmentInput[];
57
+ nav: NavInput[];
58
+ deploymentSegments: DeploymentSegmentInput[];
59
+ apiDefinitions: DeploymentApiDefinitionInput[];
60
+ /** Visible top-level products in switcher order, snapshotted for sibling sites on the same host. */
61
+ siteProducts: DocsSiteProduct[];
62
+ jsFilesHash: string | undefined;
63
+ /**
64
+ * ADR 0009: structural config (everything except `header`, `footer`,
65
+ * `css.inline`, `js.inline`) ready to be written into
66
+ * `docs_ledger_deployments.config_json` as JSONB. The four extracted
67
+ * variable-length pieces are content-addressed via the `*Hash` fields
68
+ * below.
69
+ */
70
+ configJson: unknown | undefined;
71
+ /** CAS hash for the extracted `config.header` blob, or undefined. */
72
+ headerHash: string | undefined;
73
+ /** CAS hash for the extracted `config.footer` blob, or undefined. */
74
+ footerHash: string | undefined;
75
+ /**
76
+ * CAS hash for the extracted `config.css.inline` blob (joined with
77
+ * `\n`), or undefined.
78
+ */
79
+ cssInlineHash: string | undefined;
80
+ /**
81
+ * CAS hash for the extracted `config.js.inline` blob (joined with
82
+ * `\n`), or undefined.
83
+ */
84
+ jsInlineHash: string | undefined;
85
+ domain: string;
86
+ /**
87
+ * The domain files are anchored on (defaults to `domain` when omitted
88
+ * in the input). Forwarded so callers can key S3 operations and
89
+ * manifest entries on the canonical domain for preview publishes.
90
+ */
91
+ fileDomain: string;
92
+ version?: string | null;
93
+ repo?: string | null;
94
+ /**
95
+ * Git provenance pulled straight off the publish input (ADR 0012 /
96
+ * FER-10489). Forwarded to {@link DeploymentInput} so the deployment
97
+ * row captures the repo/branch/sha used by the read path to
98
+ * synthesise `editThisPageUrl`.
99
+ */
100
+ git?: {
101
+ repoUrl: string;
102
+ branch: string;
103
+ commitSha?: string;
104
+ };
105
+ /** All content blobs referenced by this deployment (artifact content, globals, generated). */
106
+ contentRefs: Map<string, BlobRef>;
107
+ /** Blobs generated by the transform (pruned API defs). Must be uploaded to CAS. */
108
+ generatedBlobs: Map<string, GeneratedBlob>;
109
+ /**
110
+ * File manifest entries (images, fonts, pdfs). Tracked separately from
111
+ * `contentRefs` because file bytes land in the public/private docs bucket
112
+ * (key `{assetDomain}/{hash}/{fullPath}`), not in CAS. The register handler
113
+ * routes their uploads accordingly; the finish handler upserts a
114
+ * `docs_ledger_file` row per entry and resolves the resulting IDs onto
115
+ * file/image artifacts.
116
+ */
117
+ fileEntries: TransformFileEntry[];
118
+ /**
119
+ * pageId → bare `fullPath`s of the files that page's markdown embeds (ADR
120
+ * 0014, "File metadata on the render path"). Copied straight off the publish
121
+ * input's `pages[pageId].referencedFiles` (captured CLI-side). Lets the read
122
+ * model materialise the page→file join into each route shard. Empty for
123
+ * pages with no embedded files or from CLIs that predate the field.
124
+ */
125
+ referencedFilesByPageId: Record<string, string[]>;
126
+ }
127
+ /**
128
+ * Transform a single locale's content into hash-addressed entities ready for persistence.
129
+ *
130
+ * @param input - One locale entry (content fields) plus the deployment's `domain`.
131
+ * @param apiManifest - Parsed API definitions (fetched from CAS by the caller).
132
+ * Pass an empty object if there are no API references in the nav tree.
133
+ */
134
+ export declare function transformPublishInput(input: TransformInput, apiManifest?: ApiManifest): TransformResult;
135
+ /**
136
+ * Result of {@link splitConfig}: the structural `stripped` config (written
137
+ * inline as JSONB on the deployment row) plus the four extracted CAS blobs.
138
+ */
139
+ export interface SplitConfigResult {
140
+ /**
141
+ * `config` with `header`, `footer`, `css.inline`, `js.inline` removed.
142
+ * `css` / `js` are dropped entirely if `inline` was their only key.
143
+ */
144
+ stripped: Omit<LedgerConfig, "header" | "footer" | "css" | "js"> & {
145
+ css?: Omit<NonNullable<LedgerConfig["css"]>, "inline">;
146
+ js?: Omit<NonNullable<LedgerConfig["js"]>, "inline">;
147
+ };
148
+ header: string | undefined;
149
+ footer: string | undefined;
150
+ cssInline: string | undefined;
151
+ jsInline: string | undefined;
152
+ }
153
+ /**
154
+ * Split a {@link LedgerConfig} into the structural portion (to be written
155
+ * inline as JSONB) and the four variable-length fields that are extracted
156
+ * to their own CAS blobs (ADR 0009).
157
+ *
158
+ * - `header`, `footer`: returned as the raw strings if non-empty.
159
+ * - `css.inline`, `js.inline`: arrays of strings, joined with `\n` into a
160
+ * single text blob if non-empty. The `inline` key is removed from `css`
161
+ * and `js` in the stripped config; any other sibling fields (`js.files`,
162
+ * `js.remote`) are preserved. `css.inline` is currently the only field
163
+ * on `css`, so `stripped.css` is dropped in practice — the empty-keys
164
+ * check is kept for symmetry with `js` and to stay correct if the
165
+ * schema grows new `css` siblings.
166
+ *
167
+ * The returned `stripped` object is a shallow-cloned subset of `config` so
168
+ * that callers can safely mutate it without affecting the original.
169
+ *
170
+ * The input has already been validated against `LedgerConfigSchema` by
171
+ * Zod upstream — no runtime shape checks are needed here.
172
+ *
173
+ * Exported for testing.
174
+ *
175
+ * @internal
176
+ */
177
+ export declare function splitConfig(config: LedgerConfig): SplitConfigResult;
178
+ //# sourceMappingURL=docsPublishTransform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docsPublishTransform.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/docsPublishTransform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Ledger publish transform — the pure (no DB, no S3) half of a docs publish.
3
+ *
4
+ * `transformPublishInput` turns a `DocsPublishInput` locale into hashed
5
+ * content-addressed entities, and `buildLedgerReadModel` assembles the pointer
6
+ * manifest + route shards the Astro renderer reads. FDR runs these on publish;
7
+ * the Fern CLI runs the same code to render a local project without a server.
8
+ */
9
+ export * from "./buildLedgerManifest.js";
10
+ export * from "./docsLedgerHash.js";
11
+ export * from "./docsPublishTransform.js";
12
+ export * from "./inputTypes.js";
13
+ export { sha256Hex, stableHash } from "./stableHash.js";
14
+ export * from "./toBasepathRelative.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Content-addressed input entities produced by the ledger publish transform
3
+ * (`transformPublishInput`) and consumed by both FDR's `DocsLedgerDao` and the
4
+ * read-model builder (`buildLedgerReadModel`). Pure data types — no DB or
5
+ * runtime coupling — so the CLI can run the same transform for local preview.
6
+ */
7
+ import type { LedgerArtifactTypeMetadata, LedgerSegmentDetailMetadata, LedgerSegmentMetadata } from "../orpc-client/index.js";
8
+ /** Content-addressed segment detail (product/version/tab/variant metadata). */
9
+ export interface SegmentDetailInput {
10
+ hash: string;
11
+ type: string;
12
+ displayName: string;
13
+ icon?: string | null;
14
+ sortOrder: number;
15
+ metadata: LedgerSegmentDetailMetadata;
16
+ hidden: boolean;
17
+ viewers: string[];
18
+ orphaned: boolean;
19
+ featureFlags: string[];
20
+ }
21
+ /** Content-addressed artifact (page/endpoint/link/redirect/file/image). */
22
+ export type ArtifactInput = LedgerArtifactTypeMetadata & {
23
+ hash: string;
24
+ hidden: boolean;
25
+ /**
26
+ * CAS content hash. Set for pages, API defs, redirects, jsFiles, etc.
27
+ * Null for link artifacts and for file/image artifacts (those resolve via
28
+ * `fileKey` instead — see {@link FileEntryInput} and the `docs_ledger_file`
29
+ * table). The DAO resolves this to `content_id`.
30
+ */
31
+ contentHash: string | null;
32
+ /**
33
+ * File identity for file/image artifacts. Set on type=`file`/`image`,
34
+ * null otherwise. The DAO resolves this to `docs_ledger_file_id` via
35
+ * (assetDomain, hash, fullPath) — the asset domain is the canonical site
36
+ * domain passed to {@link DocsLedgerDao.persistDeployment}, while
37
+ * additional custom-domain site rows share the same uploaded file rows.
38
+ *
39
+ * Mutually exclusive with `contentHash` for content-bearing artifacts.
40
+ */
41
+ fileKey: {
42
+ hash: string;
43
+ fullPath: string;
44
+ } | null;
45
+ };
46
+ /**
47
+ * A file (image/font/etc.) tracked in `docs_ledger_file`.
48
+ *
49
+ * The publish handler determines `bucket` from the site's auth model
50
+ * before calling {@link DocsLedgerDao.persistDeployment} — the DAO upserts
51
+ * one row per unique `(domain, hash, full_path)` and resolves the resulting
52
+ * IDs onto file/image artifacts. Custom domains do not get duplicate file
53
+ * rows; they resolve to the canonical site's uploaded asset namespace.
54
+ */
55
+ export interface FileEntryInput {
56
+ fullPath: string;
57
+ hash: string;
58
+ contentType: string;
59
+ /** Which S3 bucket the bytes were uploaded to. */
60
+ bucket: "public_docs" | "private_docs";
61
+ }
62
+ /**
63
+ * Content-addressed segment.
64
+ * References segment details by hash (resolved to database IDs during publish).
65
+ */
66
+ export interface SegmentInput {
67
+ hash: string;
68
+ locale: string;
69
+ productHash?: string;
70
+ versionHash?: string;
71
+ variantHash?: string;
72
+ tabHash?: string;
73
+ section: string;
74
+ metadata: LedgerSegmentMetadata;
75
+ hidden: boolean;
76
+ }
77
+ /**
78
+ * Unified nav entry: routing + sidebar ordering in one row.
79
+ * - fullPath non-null = routable (path lookup)
80
+ * - displaySortOrder non-null = shows in sidebar
81
+ * - Both non-null = canonical route (routable + in sidebar)
82
+ * - fullPath null = sidebar-only (external links, folders)
83
+ * - displaySortOrder null = route-only (non-canonical aliases)
84
+ */
85
+ export interface NavInput {
86
+ segmentHash: string;
87
+ artifactHash: string;
88
+ fullPath?: string;
89
+ displaySortOrder?: number;
90
+ }
91
+ /** Immutable deployment snapshot. */
92
+ export interface DeploymentInput {
93
+ id: string;
94
+ hash: string;
95
+ version?: string;
96
+ repo?: string;
97
+ jsFilesHash?: string;
98
+ /**
99
+ * Structural config (stripped of `header`, `footer`, `css.inline`,
100
+ * `js.inline`) to be written inline into `config_json`. The four
101
+ * extracted variable-length pieces are content-addressed below.
102
+ */
103
+ configJson?: unknown;
104
+ /** CAS hash for the extracted `config.header` blob. */
105
+ headerHash?: string;
106
+ /** CAS hash for the extracted `config.footer` blob. */
107
+ footerHash?: string;
108
+ /** CAS hash for the extracted joined `config.css.inline` blob. */
109
+ cssInlineHash?: string;
110
+ /** CAS hash for the extracted joined `config.js.inline` blob. */
111
+ jsInlineHash?: string;
112
+ createdBy?: string;
113
+ /**
114
+ * Git provenance (ADR 0012 / FER-10489). Captured from the CLI publish
115
+ * input so the read path can synthesise `editThisPageUrl`. All optional —
116
+ * CLIs that omit `git` map to NULL columns.
117
+ */
118
+ gitRepoUrl?: string;
119
+ gitBranch?: string;
120
+ gitCommitSha?: string;
121
+ /** Default locale for this deployment (extracted from config_json.translations). */
122
+ defaultLocale?: string;
123
+ /** All locales supported by this deployment (including the default). */
124
+ translations?: string[];
125
+ /** FDR server version that produced this deployment (for cache-busting diagnostics). */
126
+ fdrVersion?: string;
127
+ /** Fern CLI version that produced this deployment (from X-CLI-Version header). */
128
+ cliVersion?: string;
129
+ }
130
+ /** Deployment → segment join entry (referenced by segment hash). */
131
+ export interface DeploymentSegmentInput {
132
+ segmentHash: string;
133
+ sortOrder: number;
134
+ }
135
+ /** Deployment → API definition join entry. */
136
+ export interface DeploymentApiDefinitionInput {
137
+ apiDefinitionId: string;
138
+ apiName: string | null;
139
+ contentHash: string;
140
+ }
141
+ /** New site row in the append-only site log. */
142
+ export interface SiteInput {
143
+ id: string;
144
+ orgId: string;
145
+ domain: string;
146
+ basepath: string;
147
+ previewId?: string;
148
+ assignedBy?: string;
149
+ }
150
+ /** Parameters for adding translation segments to an existing deployment. */
151
+ export interface TranslationSegmentParams {
152
+ deploymentId: string;
153
+ /** Owning org — CAS content/artifacts/segments are org-scoped (ADR 0008). */
154
+ orgId: string;
155
+ domain: string;
156
+ segmentDetails: SegmentDetailInput[];
157
+ artifacts: ArtifactInput[];
158
+ segments: SegmentInput[];
159
+ nav: NavInput[];
160
+ deploymentSegments: DeploymentSegmentInput[];
161
+ files: FileEntryInput[];
162
+ }
163
+ /**
164
+ * Translation segment params without `deploymentId` — the ID is determined
165
+ * inside the `persistDeployment` transaction and injected automatically.
166
+ */
167
+ export type InlineTranslationParams = Omit<TranslationSegmentParams, "deploymentId"> & {
168
+ locale: string;
169
+ /** Locale's structural config (translation overlay applied). Read-model only; not persisted to postgres. */
170
+ configJson?: unknown;
171
+ };
172
+ /** A product of a published site as stored in `docs_sites.products` (JSON). */
173
+ export type DocsSiteProduct = {
174
+ title: string;
175
+ /** Absolute href on the host (`/{basepath}/{slug}/`) or an external URL for product links. */
176
+ href: string;
177
+ subtitle?: string;
178
+ };
179
+ /** Everything needed to atomically publish a deployment. */
180
+ export interface PublishParams {
181
+ segmentDetails: SegmentDetailInput[];
182
+ artifacts: ArtifactInput[];
183
+ segments: SegmentInput[];
184
+ nav: NavInput[];
185
+ deployment: DeploymentInput;
186
+ deploymentSegments: DeploymentSegmentInput[];
187
+ apiDefinitions: DeploymentApiDefinitionInput[];
188
+ /**
189
+ * Canonical (fern URL) site row. Always inserted into `docs_ledger_site`,
190
+ * and serves as the anchor for `docs_ledger_file` rows (file bytes live
191
+ * at `{site.domain}/{hash}/{fullPath}` regardless of how many extra
192
+ * domains the deployment is served from — see ADR 0010).
193
+ */
194
+ site: SiteInput;
195
+ /**
196
+ * Additional site rows for custom domains attached to the same
197
+ * deployment (ADR 0010). One row per (domain, basepath) pair, all
198
+ * pointing at the same `deployment_id`. No file rows fan out — the
199
+ * fern site (above) is the file-row anchor.
200
+ */
201
+ additionalSites?: SiteInput[];
202
+ /**
203
+ * Files referenced by file/image artifacts. The DAO upserts one
204
+ * `docs_ledger_file` row per `(domain, hash, full_path)` inside the
205
+ * publish transaction, then resolves each file/image artifact's
206
+ * `docs_ledger_file_id` from its `fileKey`.
207
+ *
208
+ * The domain is taken from `site.domain` (the canonical fern URL) —
209
+ * file rows are anchored on the fern domain even for multi-domain
210
+ * publishes, per ADR 0010.
211
+ */
212
+ files: FileEntryInput[];
213
+ /**
214
+ * Domain used for file anchoring (S3 keys + `docs_ledger_file` rows).
215
+ * When set, overrides `site.domain` for file operations so that
216
+ * preview publishes anchor files on the canonical fern domain
217
+ * (ADR 0010) instead of the ephemeral preview hostname.
218
+ */
219
+ fileDomain?: string;
220
+ /**
221
+ * Optional inline translations to persist atomically with the base
222
+ * deployment. When provided, translation segments are inserted inside
223
+ * the same DB transaction as the base deployment — fully atomic.
224
+ */
225
+ inlineTranslations?: InlineTranslationParams[];
226
+ }
227
+ /** Metadata stored on file/image artifacts. */
228
+ export type FileArtifactMetadata = {
229
+ contentType: string;
230
+ contentLength?: number;
231
+ filename: string;
232
+ width?: number;
233
+ height?: number;
234
+ blurDataURL?: string;
235
+ };
236
+ //# sourceMappingURL=inputTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputTypes.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/inputTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { stableStringify } from "../orpc-client/index.js";
2
+ export { stableStringify };
3
+ /** SHA-256 hex digest of the input string. */
4
+ export declare function sha256Hex(input: string): string;
5
+ /** Convenience: stable JSON + sha256 in one call. */
6
+ export declare function stableHash(value: unknown): string;
7
+ //# sourceMappingURL=stableHash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stableHash.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/stableHash.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK1D,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Strip exactly one leading `${basePrefix}/` (or a bare `basePrefix`) from
3
+ * `fullPath`, yielding the basepath-RELATIVE remainder.
4
+ *
5
+ * Lives in its own leaf module because both `docsPublishTransform` and
6
+ * `buildLedgerManifest` need it but cannot share a value import with each
7
+ * other (`buildLedgerManifest` already imports `docsPublishTransform`'s
8
+ * types).
9
+ *
10
+ * Write side (`buildLedgerManifest`): every fullPath the transform produces
11
+ * is basepath-rooted, so stripping the first segment is unambiguous — even
12
+ * for the pathological `docs/docs` page (the second segment is the page's
13
+ * own slug). Only `navBySegment` keys are made relative; `routes`, `routing`,
14
+ * `versionFirstRoute`, and `pages` keys stay ABSOLUTE.
15
+ *
16
+ * Transform side (`docsPublishTransform`): normalises a reconstructed
17
+ * link-redirect parent slug before it is re-prefixed with the basepath. Most
18
+ * products yield a basepath-relative parent slug (`astro`), but the root/home
19
+ * product (`slug: /`) has an accumulated V1 slug that already equals the
20
+ * basepath (`docs`) — `extractSlugSegment` cannot strip it, so the product
21
+ * slug leaks the basepath. Normalising here makes the subsequent single
22
+ * prefix idempotent and prevents a `docs/docs/...` key.
23
+ */
24
+ export declare function toBasepathRelative(fullPath: string, basePrefix: string): string;
25
+ //# sourceMappingURL=toBasepathRelative.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toBasepathRelative.d.ts","sourceRoot":"","sources":["../../../src/docs-ledger/toBasepathRelative.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAS/E"}