@takuhon/api 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.d.ts +137 -2
- package/dist/index.js +613 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,8 @@ Hono-based HTTP route handlers, RFC 7807 Problem Details error envelope, and res
|
|
|
4
4
|
|
|
5
5
|
Ships:
|
|
6
6
|
|
|
7
|
-
- `createPublicApp({ storage })` —
|
|
7
|
+
- `createPublicApp({ storage })` — the server-rendered profile page at `GET /` (and `/<locale>/`) with Schema.org JSON-LD embedded in the HTML, plus the public read endpoints (`/api/profile`, `/api/jsonld`, `/api/schema`, `/takuhon.json`) and `/.well-known/takuhon.json`
|
|
8
|
+
- `renderProfileHtml` / `generateSite` / `renderCvHtml` — pure, `@takuhon/core`-only static HTML rendering (no DOM, no bundler) shared by the `GET /` route and `@takuhon/cli`'s `build` / `dev`
|
|
8
9
|
- `createAdminApiApp({ storage, bearerToken, originAllowlist, cachePurger, auditLogger })` — `PUT`/`DELETE /api/admin/profile` with optimistic locking (`If-Match`), audit logging, and edge-cache purging
|
|
9
10
|
- `createAdminUiApp()` — minimal HTML admin editor (token + JSON textarea + Save/Delete)
|
|
10
11
|
- `CachePurger` and `AuditLogger` dependency-injection interfaces (with `noopCachePurger` / `noopAuditLogger` no-op implementations)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context, Hono } from 'hono';
|
|
2
2
|
import { ContentfulStatusCode } from 'hono/utils/http-status';
|
|
3
|
-
import { TakuhonStorage, Takuhon, ActivityStorage, TakuhonAssetStorage } from '@takuhon/core';
|
|
3
|
+
import { TakuhonStorage, Takuhon, ActivityStorage, TakuhonAssetStorage, LocalizedTakuhon, ActivitySnapshot, NormalizedTakuhon, CvDocument } from '@takuhon/core';
|
|
4
4
|
export { applyPublicPrivacyFilter } from '@takuhon/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -235,4 +235,139 @@ declare function createAdminUiApp(): Hono;
|
|
|
235
235
|
*/
|
|
236
236
|
declare function adminAssetSecurityHeaders(): Record<string, string>;
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
/**
|
|
239
|
+
* Pure HTML helpers shared by the static-site renderer ({@link
|
|
240
|
+
* import('./build-html.js')}) and the CV renderer ({@link
|
|
241
|
+
* import('./cv-html.js')}). All are string-in / string-out with no I/O, so they
|
|
242
|
+
* stay unit-testable and keep both renderers' escaping behavior identical.
|
|
243
|
+
*/
|
|
244
|
+
/** Escape text for use in HTML element content or double/single-quoted attributes. */
|
|
245
|
+
declare function escapeHtml(value: string): string;
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Pure HTML rendering for `takuhon build`.
|
|
249
|
+
*
|
|
250
|
+
* {@link renderProfileHtml} turns one locale-resolved {@link LocalizedTakuhon}
|
|
251
|
+
* into a complete, self-contained static HTML document: semantic markup for
|
|
252
|
+
* every profile section, an inline stylesheet, optional Schema.org JSON-LD,
|
|
253
|
+
* and the `<head>` metadata (`<title>`, description, canonical, hreflang
|
|
254
|
+
* alternates) the caller supplies.
|
|
255
|
+
*
|
|
256
|
+
* This is a deliberately separate, simpler surface from the React
|
|
257
|
+
* `@takuhon/ui` (which is delivered as CSS-Modules components needing a
|
|
258
|
+
* bundler). It reuses only `@takuhon/core` and has no DOM/browser dependency,
|
|
259
|
+
* so it renders in plain Node and is unit-testable as a pure string function.
|
|
260
|
+
*
|
|
261
|
+
* Security: every piece of profile-derived text is escaped before it reaches
|
|
262
|
+
* the markup ({@link escapeHtml}), and the JSON-LD payload is `<`/`>`/`&`
|
|
263
|
+
* unicode-escaped so it cannot break out of its `<script>` element.
|
|
264
|
+
*/
|
|
265
|
+
|
|
266
|
+
/** One entry in the human-facing locale switcher. */
|
|
267
|
+
interface LocaleLink {
|
|
268
|
+
locale: string;
|
|
269
|
+
href: string;
|
|
270
|
+
current: boolean;
|
|
271
|
+
}
|
|
272
|
+
/** One `<link rel="alternate" hreflang>` entry. */
|
|
273
|
+
interface Alternate {
|
|
274
|
+
hreflang: string;
|
|
275
|
+
href: string;
|
|
276
|
+
}
|
|
277
|
+
interface RenderInput {
|
|
278
|
+
/** The locale-resolved document to render. */
|
|
279
|
+
localized: LocalizedTakuhon;
|
|
280
|
+
/** Absolute canonical URL for this page (only when `--base-url` was given). */
|
|
281
|
+
canonicalUrl?: string;
|
|
282
|
+
/** hreflang alternates (empty when no base URL is available). */
|
|
283
|
+
alternates: readonly Alternate[];
|
|
284
|
+
/** Human locale switcher links (rendered only when more than one locale). */
|
|
285
|
+
localeNav: readonly LocaleLink[];
|
|
286
|
+
/** Whether to emit Schema.org JSON-LD (mirrors `settings.enableJsonLd`). */
|
|
287
|
+
jsonLd: boolean;
|
|
288
|
+
/**
|
|
289
|
+
* Synced developer-activity snapshot, rendered as a self-owned inline SVG
|
|
290
|
+
* section. The caller gates it on `settings.activity.enabled`; an absent (or
|
|
291
|
+
* metric-less) snapshot omits the section entirely.
|
|
292
|
+
*/
|
|
293
|
+
activitySnapshot?: ActivitySnapshot;
|
|
294
|
+
}
|
|
295
|
+
/** Render a complete static HTML document for one locale-resolved profile. */
|
|
296
|
+
declare function renderProfileHtml(input: RenderInput): string;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Shared static-site generation for `takuhon build` and `takuhon dev`.
|
|
300
|
+
*
|
|
301
|
+
* {@link generateSite} turns one validated, normalized, privacy-filtered profile
|
|
302
|
+
* into the full set of pages the static surface exposes: one per available
|
|
303
|
+
* locale. `build` writes each page's {@link SitePage.file} to disk; `dev` serves
|
|
304
|
+
* each page's {@link SitePage.route} from memory. Keeping the per-locale loop,
|
|
305
|
+
* the locale switcher links, and the canonical/hreflang logic here means both
|
|
306
|
+
* commands share a single source of truth for the site's structure — the only
|
|
307
|
+
* difference between them is disk write vs. in-memory serve.
|
|
308
|
+
*
|
|
309
|
+
* This reuses `@takuhon/core` only (validate/normalize/resolve happen upstream;
|
|
310
|
+
* this module just resolves each locale and renders), so it stays bundler-free
|
|
311
|
+
* and unit-testable as a pure function.
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
/** One generated page: a serve route, a relative output file, and its HTML. */
|
|
315
|
+
interface SitePage {
|
|
316
|
+
/** URL path used by `dev` (default locale at `/`, others at `/<locale>/`). */
|
|
317
|
+
readonly route: string;
|
|
318
|
+
/** Output path used by `build`, relative to the output dir. */
|
|
319
|
+
readonly file: string;
|
|
320
|
+
/** Rendered HTML document. */
|
|
321
|
+
readonly html: string;
|
|
322
|
+
}
|
|
323
|
+
interface GenerateOptions {
|
|
324
|
+
/**
|
|
325
|
+
* Site origin (e.g. `https://me.example`). When set, pages carry absolute
|
|
326
|
+
* canonical + hreflang links; when absent those are omitted (the human locale
|
|
327
|
+
* switcher is always relative either way).
|
|
328
|
+
*/
|
|
329
|
+
readonly baseUrl?: string;
|
|
330
|
+
/**
|
|
331
|
+
* Synced developer-activity snapshot (the `activity.json` beside the
|
|
332
|
+
* profile). Rendered as an inline-SVG section only while
|
|
333
|
+
* `settings.activity.enabled` is true — the same opt-in gate the public
|
|
334
|
+
* `GET /api/activity` applies — so disabling the feature drops the section
|
|
335
|
+
* even if a stale snapshot remains on disk. The snapshot is locale-agnostic
|
|
336
|
+
* and shared by every page.
|
|
337
|
+
*/
|
|
338
|
+
readonly activitySnapshot?: ActivitySnapshot | null;
|
|
339
|
+
/**
|
|
340
|
+
* Also emit a print-ready CV/résumé page per locale (the default locale at
|
|
341
|
+
* `cv.html` / route `/cv/`, others at `<locale>/cv.html` / `/<locale>/cv/`).
|
|
342
|
+
* `takuhon build` gates this behind `--cv`; `takuhon dev` always enables it so
|
|
343
|
+
* the page is previewable. Off by default, so a plain build is unchanged.
|
|
344
|
+
*/
|
|
345
|
+
readonly cv?: boolean;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Generate every page for a profile: the default locale first, then the rest,
|
|
349
|
+
* de-duplicated. Schema.org JSON-LD is emitted unless `settings.enableJsonLd`
|
|
350
|
+
* is explicitly `false`.
|
|
351
|
+
*/
|
|
352
|
+
declare function generateSite(profile: NormalizedTakuhon, options?: GenerateOptions): SitePage[];
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Pure HTML rendering of a {@link CvDocument} for `takuhon build --cv`.
|
|
356
|
+
*
|
|
357
|
+
* {@link renderCvHtml} turns one locale-resolved CV (from `@takuhon/core`'s
|
|
358
|
+
* {@link deriveCv}) into a complete, self-contained static HTML résumé: an
|
|
359
|
+
* inline stylesheet sized for A4 with an `@media print` block, so the page
|
|
360
|
+
* reads well on screen and the browser's "Save as PDF" produces a clean,
|
|
361
|
+
* single-column résumé. No external resources are referenced, so the page works
|
|
362
|
+
* under a strict `img-src 'self'` / no-network policy (the same self-owned
|
|
363
|
+
* stance the profile page and the activity card take).
|
|
364
|
+
*
|
|
365
|
+
* Security: every CV-derived string is escaped before it reaches the markup
|
|
366
|
+
* ({@link escapeHtml}), and any URL is scheme-checked ({@link safeUrl}) so a
|
|
367
|
+
* hostile document cannot smuggle a `javascript:` href into the résumé.
|
|
368
|
+
*/
|
|
369
|
+
|
|
370
|
+
/** Render a complete static HTML résumé document for one locale-resolved CV. */
|
|
371
|
+
declare function renderCvHtml(cv: CvDocument): string;
|
|
372
|
+
|
|
373
|
+
export { type AdminApiAppDeps, type Alternate, type AuditEvent, type AuditEventType, type AuditLogger, type BuildProblemInput, type CachePurger, ERROR_SLUGS, type ErrorSlug, type GenerateOptions, LOCALE_AWARE_REMAINDERS, type LocaleLink, type ProblemDetails, type ProblemFieldError, type ProblemResponseInput, type PublicAppDeps, type RenderInput, type SitePage, adminAssetSecurityHeaders, buildProblem, createAdminApiApp, createAdminUiApp, createPublicApp, escapeHtml, generateSite, localePrefixGetPath, noopAuditLogger, noopCachePurger, pathLocaleFromUrl, problemResponse, renderCvHtml, renderProfileHtml, stripLocalePrefix };
|