@notion-headless-cms/core 0.3.20 → 0.3.22
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 +0 -1
- package/dist/cache/memory.d.mts +25 -2
- package/dist/{memory-BT9rLPr1.d.mts → cache-DS81aOcC.d.mts} +2 -23
- package/dist/config-D4JQ_pmq.d.mts +150 -0
- package/dist/{errors-CC_x98vG.d.mts → errors-DTt9ii0i.d.mts} +12 -1
- package/dist/errors.d.mts +1 -1
- package/dist/errors.mjs +19 -0
- package/dist/errors.mjs.map +1 -1
- package/dist/hooks.d.mts +17 -2
- package/dist/html.d.mts +14 -8
- package/dist/html.mjs +12 -2
- package/dist/html.mjs.map +1 -1
- package/dist/index.d.mts +23 -267
- package/dist/index.mjs +32 -56
- package/dist/index.mjs.map +1 -1
- package/dist/{hooks-C6F2PG8x.d.mts → plugin-B795Ok3X.d.mts} +3 -15
- package/dist/preset/node.d.mts +33 -0
- package/dist/preset/node.mjs +26 -0
- package/dist/preset/node.mjs.map +1 -0
- package/dist/source-author.d.mts +3 -0
- package/dist/source-author.mjs +1 -0
- package/package.json +12 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { a as CachedItemMeta, c as ContentResult, i as CachedItemList, l as ImageRef, n as CMSSchemaProperties, o as StorageBinary, r as CachedItemContent, s as ContentBlock, t as BaseContentItem, u as InlineNode } from "./content-DwsfWZao.mjs";
|
|
2
|
-
import { a as
|
|
3
|
-
import { a as isCMSError, i as CMSErrorContext, n as CMSError, o as isCMSErrorInNamespace, r as CMSErrorCode, s as matchCMSError, t as BuiltInCMSErrorCode } from "./errors-
|
|
4
|
-
import { a as
|
|
2
|
+
import { a as InvalidateKind, c as PropertyMap, i as DataSource, l as WebhookConfig, n as DocumentCacheOps, o as InvalidateScope, r as ImageCacheOps, s as PropertyDef, t as CacheAdapter } from "./cache-DS81aOcC.mjs";
|
|
3
|
+
import { a as isCMSError, i as CMSErrorContext, n as CMSError, o as isCMSErrorInNamespace, r as CMSErrorCode, s as matchCMSError, t as BuiltInCMSErrorCode } from "./errors-DTt9ii0i.mjs";
|
|
4
|
+
import { a as MaybePromise, i as CMSHooks, n as definePlugin, r as Logger, t as CMSPlugin } from "./plugin-B795Ok3X.mjs";
|
|
5
|
+
import { a as InferCollectionItem, c as RenderOptions, d as SWRConfig, i as CreateClientOptions, l as RendererFn, m as MergeSourceCollections, n as CollectionsConfig, o as LogLevel, p as CMSSources, r as ContentConfig, s as RateLimiterConfig, u as RendererPluginList } from "./config-D4JQ_pmq.mjs";
|
|
6
|
+
import { MemoryCacheOptions, memoryCache } from "./cache/memory.mjs";
|
|
7
|
+
import { mergeHooks, mergeLoggers } from "./hooks.mjs";
|
|
8
|
+
import { NodePresetOptions, nodePreset } from "./preset/node.mjs";
|
|
5
9
|
|
|
6
10
|
//#region src/types/collection.d.ts
|
|
7
11
|
/**
|
|
@@ -136,162 +140,6 @@ interface CollectionClient<T extends BaseContentItem = BaseContentItem> {
|
|
|
136
140
|
cache: CollectionCacheOps<T>;
|
|
137
141
|
}
|
|
138
142
|
//#endregion
|
|
139
|
-
//#region src/types/sources.d.ts
|
|
140
|
-
/**
|
|
141
|
-
* CMS データソースアダプターのインターフェース。
|
|
142
|
-
* 各アダプターパッケージ (`@notion-headless-cms/notion-source` 等) が実装し、
|
|
143
|
-
* `createClient({ sources: { ... } })` に渡される。
|
|
144
|
-
*/
|
|
145
|
-
interface CMSAdapter<C extends CollectionsConfig = CollectionsConfig> {
|
|
146
|
-
readonly collections: C;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* アダプターパッケージが宣言マージで拡張する空インターフェース。
|
|
150
|
-
* import するだけでキーが補完候補に現れる (Fastify プラグインと同じパターン)。
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* declare module "@notion-headless-cms/core" {
|
|
154
|
-
* interface CMSSources {
|
|
155
|
-
* notion?: CMSAdapter;
|
|
156
|
-
* }
|
|
157
|
-
* }
|
|
158
|
-
*/
|
|
159
|
-
interface CMSSources {}
|
|
160
|
-
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
161
|
-
/** 全ソースの collections を交差型でマージする。 */
|
|
162
|
-
type MergeSourceCollections<S extends CMSSources> = UnionToIntersection<{ [K in keyof S]: S[K] extends CMSAdapter<infer C> ? C : never }[keyof S]>;
|
|
163
|
-
//#endregion
|
|
164
|
-
//#region src/types/config.d.ts
|
|
165
|
-
/** `Logger` の出力を絞り込むログレベル。指定したレベル未満のログを抑制する。 */
|
|
166
|
-
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
167
|
-
/**
|
|
168
|
-
* renderer プラグインの不透明型。
|
|
169
|
-
* core は unified / remark / rehype に依存せず、このリストをそのまま renderer に渡すだけ。
|
|
170
|
-
*/
|
|
171
|
-
type RendererPluginList = unknown[];
|
|
172
|
-
/**
|
|
173
|
-
* render() オプション。core は renderer の実装を知らず、この型だけを扱う。
|
|
174
|
-
* @notion-headless-cms/renderer の renderMarkdown() はこのシグネチャと構造的に互換。
|
|
175
|
-
*/
|
|
176
|
-
interface RenderOptions {
|
|
177
|
-
imageProxyBase?: string;
|
|
178
|
-
cacheImage?: (url: string) => Promise<string>;
|
|
179
|
-
remarkPlugins?: RendererPluginList;
|
|
180
|
-
rehypePlugins?: RendererPluginList;
|
|
181
|
-
}
|
|
182
|
-
/** カスタムレンダラー関数の型。デフォルトは @notion-headless-cms/renderer の renderMarkdown。 */
|
|
183
|
-
type RendererFn = (markdown: string, opts?: RenderOptions) => Promise<string>;
|
|
184
|
-
/** レンダリング・コンテンツ処理設定。 */
|
|
185
|
-
interface ContentConfig {
|
|
186
|
-
/** 画像プロキシのベースURL。デフォルト: '/api/images' */
|
|
187
|
-
imageProxyBase?: string;
|
|
188
|
-
/** 追加する remark プラグイン。 */
|
|
189
|
-
remarkPlugins?: RendererPluginList;
|
|
190
|
-
/** 追加する rehype プラグイン。 */
|
|
191
|
-
rehypePlugins?: RendererPluginList;
|
|
192
|
-
}
|
|
193
|
-
/** SWR(Stale-While-Revalidate)設定。 */
|
|
194
|
-
interface SWRConfig {
|
|
195
|
-
/** SWR の有効期間 (ミリ秒)。未設定時は TTL なし(失効まで stale を返す)。 */
|
|
196
|
-
ttlMs?: number;
|
|
197
|
-
}
|
|
198
|
-
/** レートリミット・リトライ設定。 */
|
|
199
|
-
interface RateLimiterConfig {
|
|
200
|
-
/** 同時実行数の上限。デフォルト: 3 */
|
|
201
|
-
maxConcurrent?: number;
|
|
202
|
-
/** リトライ対象の HTTP ステータスコード。デフォルト: [429, 502, 503] */
|
|
203
|
-
retryOn?: number[];
|
|
204
|
-
/** 最大リトライ回数。デフォルト: 4 */
|
|
205
|
-
maxRetries?: number;
|
|
206
|
-
/** リトライ時の基準待機時間(ミリ秒)。デフォルト: 1000 */
|
|
207
|
-
baseDelayMs?: number;
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* コレクション 1 件の定義。CLI が生成する `nhc.ts` から `createClient` に渡される。
|
|
211
|
-
*
|
|
212
|
-
* `source` は notion-orm 等の DataSource 実装。
|
|
213
|
-
* `slugField` / `statusField` は TS フィールド名 (DataSource の `properties` キーと一致)。
|
|
214
|
-
*/
|
|
215
|
-
interface CollectionDef<T extends BaseContentItem = BaseContentItem> {
|
|
216
|
-
/** Notion etc. のデータソース実装。 */
|
|
217
|
-
source: DataSource<T>;
|
|
218
|
-
/** slug として使う TS フィールド名 (必須)。`source.properties[slugField]` で Notion プロパティ名を解決する。 */
|
|
219
|
-
slugField: string;
|
|
220
|
-
/** ステータスとして使う TS フィールド名。 */
|
|
221
|
-
statusField?: string;
|
|
222
|
-
/** 公開扱いするステータス値。`list()` のデフォルト絞り込みに使う。 */
|
|
223
|
-
publishedStatuses?: readonly string[];
|
|
224
|
-
/** アクセス許可するステータス値。`get()` の閲覧可否判定に使う。 */
|
|
225
|
-
accessibleStatuses?: readonly string[];
|
|
226
|
-
/** コレクション固有のライフサイクルフック。グローバル hooks の後に実行される。 */
|
|
227
|
-
hooks?: CMSHooks<T>;
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* `createClient({ collections })` の map 型。
|
|
231
|
-
* キーがコレクション名、値が `CollectionDef<T>`。
|
|
232
|
-
*/
|
|
233
|
-
type CollectionsConfig = Record<string, CollectionDef<BaseContentItem>>;
|
|
234
|
-
/** `CollectionsConfig` から各 T を抽出するユーティリティ型。 */
|
|
235
|
-
type InferCollectionItem<C> = C extends CollectionDef<infer T> ? T : BaseContentItem;
|
|
236
|
-
/**
|
|
237
|
-
* `createClient()` の入力。
|
|
238
|
-
* 通常は CLI が生成した `nhc.ts` の `createClient` がこの型をラップする。
|
|
239
|
-
*
|
|
240
|
-
* @example
|
|
241
|
-
* createClient({
|
|
242
|
-
* collections: {
|
|
243
|
-
* posts: {
|
|
244
|
-
* source: createNotionCollection({ token, dataSourceId, properties }),
|
|
245
|
-
* slugField: "slug",
|
|
246
|
-
* statusField: "status",
|
|
247
|
-
* publishedStatuses: ["公開済み"],
|
|
248
|
-
* }
|
|
249
|
-
* },
|
|
250
|
-
* cache: [memoryCache()],
|
|
251
|
-
* swr: { ttlMs: 5 * 60_000 },
|
|
252
|
-
* });
|
|
253
|
-
*/
|
|
254
|
-
interface CreateClientOptions<C extends CollectionsConfig = CollectionsConfig, S extends CMSSources = CMSSources> {
|
|
255
|
-
/**
|
|
256
|
-
* データソースアダプター (`@notion-headless-cms/notion-source` 等) のマップ。
|
|
257
|
-
* `sources` を指定する場合 `collections` は不要。両方指定された場合は `sources` が優先される。
|
|
258
|
-
*/
|
|
259
|
-
sources?: S;
|
|
260
|
-
/** コレクション定義のマップ。`sources` を使う場合は不要。 */
|
|
261
|
-
collections?: C;
|
|
262
|
-
/**
|
|
263
|
-
* キャッシュアダプタ (配列)。未指定時はキャッシュなし。
|
|
264
|
-
* - `memoryCache()` のように doc + image 両方を担当するもの
|
|
265
|
-
* - `r2Cache()` (image のみ)、`kvCache()` (doc のみ) のように片側のみ担当するもの
|
|
266
|
-
* - 複数 adapter を配列で組み合わせると、各 adapter の `handles` で振り分けられる
|
|
267
|
-
*/
|
|
268
|
-
cache?: readonly CacheAdapter[];
|
|
269
|
-
/** SWR(Stale-While-Revalidate)設定。 */
|
|
270
|
-
swr?: SWRConfig;
|
|
271
|
-
/**
|
|
272
|
-
* Markdown→HTML レンダラー。
|
|
273
|
-
* 省略時は `@notion-headless-cms/renderer` の `renderMarkdown` を動的 import で使用する。
|
|
274
|
-
* カスタム実装も `RendererFn` 型を満たせば使用可能。
|
|
275
|
-
*/
|
|
276
|
-
renderer?: RendererFn;
|
|
277
|
-
/** 画像プロキシのベース URL。デフォルト `/api/images`。 */
|
|
278
|
-
imageProxyBase?: string;
|
|
279
|
-
/** Cloudflare Workers の `waitUntil` に相当する非同期処理の登録関数。 */
|
|
280
|
-
waitUntil?: (p: Promise<unknown>) => void;
|
|
281
|
-
/** ライフサイクルフック (全コレクション共通)。 */
|
|
282
|
-
hooks?: CMSHooks<BaseContentItem>;
|
|
283
|
-
/** プラグイン配列。 */
|
|
284
|
-
plugins?: CMSPlugin<BaseContentItem>[];
|
|
285
|
-
/** ロガー。 */
|
|
286
|
-
logger?: Logger;
|
|
287
|
-
/** ログレベルの下限。指定したレベル未満のログを内部で抑制する。 */
|
|
288
|
-
logLevel?: LogLevel;
|
|
289
|
-
/** レートリミット・リトライ設定。 */
|
|
290
|
-
rateLimiter?: RateLimiterConfig;
|
|
291
|
-
/** レンダリング・コンテンツ処理設定。 */
|
|
292
|
-
content?: ContentConfig;
|
|
293
|
-
}
|
|
294
|
-
//#endregion
|
|
295
143
|
//#region src/cache.d.ts
|
|
296
144
|
/** 文字列をSHA-256でハッシュ化し、16進数文字列として返す。画像キーの生成に使用。 */
|
|
297
145
|
declare function sha256Hex(input: string): Promise<string>;
|
|
@@ -345,65 +193,37 @@ interface HandlerAdapter {
|
|
|
345
193
|
declare function createHandler(adapter: HandlerAdapter, opts?: HandlerOptions): (req: Request) => Promise<Response>;
|
|
346
194
|
//#endregion
|
|
347
195
|
//#region src/cms.d.ts
|
|
348
|
-
/**
|
|
196
|
+
/** コレクション別アクセス + グローバル操作の合成型。 */
|
|
349
197
|
type CMSClient<C extends CollectionsConfig> = { [K in keyof C]: CollectionClient<InferCollectionItem<C[K]>> } & CMSGlobalOps;
|
|
350
|
-
/** `CMSClient` のグローバル名前空間。 */
|
|
351
198
|
interface CMSGlobalOps {
|
|
352
|
-
/** 登録されているコレクション名の一覧。 */
|
|
353
199
|
readonly collections: readonly string[];
|
|
354
|
-
/** 全コレクションまたは特定スコープのキャッシュを無効化する。 */
|
|
355
200
|
invalidate(scope?: InvalidateScope): Promise<void>;
|
|
356
|
-
/** Web Standard
|
|
201
|
+
/** Web Standard な Request/Response ベースのルートハンドラ (画像プロキシ + webhook)。 */
|
|
357
202
|
handler(opts?: HandlerOptions): (req: Request) => Promise<Response>;
|
|
358
|
-
/** ハッシュキーでキャッシュ画像を取得する。 */
|
|
359
203
|
getCachedImage(hash: string): Promise<StorageBinary | null>;
|
|
360
204
|
/**
|
|
361
|
-
* Notion 画像 URL を `{imageProxyBase}/{sha256}`
|
|
362
|
-
* 画像キャッシュが未設定 (noop) の場合は `undefined`。
|
|
363
|
-
* `resolveBlockImageUrls` などサーバー側で URL 書き換えに使う。
|
|
205
|
+
* Notion 画像 URL を `{imageProxyBase}/{sha256}` 形式へ変換しキャッシュへ書き込む。
|
|
206
|
+
* 画像キャッシュが未設定 (noop) の場合は `undefined`。
|
|
364
207
|
*/
|
|
365
208
|
readonly cacheImage: ((url: string) => Promise<string>) | undefined;
|
|
366
|
-
/**
|
|
367
|
-
* 画像プロキシのベース URL (`createClient({ imageProxyBase })`)。
|
|
368
|
-
* デフォルト `/api/images`。
|
|
369
|
-
*/
|
|
370
209
|
readonly imageProxyBase: string;
|
|
371
210
|
}
|
|
372
211
|
/**
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* 通常はユーザーが直接呼ぶことはなく、CLI 生成の `nhc.ts` の `createClient`
|
|
376
|
-
* (低レベルのこの関数をラップしたもの) を経由する。
|
|
212
|
+
* CMS クライアントを生成する。
|
|
377
213
|
*
|
|
378
214
|
* @example
|
|
379
|
-
* createClient
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* }
|
|
387
|
-
* },
|
|
388
|
-
* cache: [memoryCache()],
|
|
389
|
-
* swr: { ttlMs: 5 * 60_000 },
|
|
215
|
+
* import { createClient, nodePreset } from "@notion-headless-cms/core";
|
|
216
|
+
* import { notionSource } from "@notion-headless-cms/notion-source";
|
|
217
|
+
* import { schema } from "./generated/nhc.schema";
|
|
218
|
+
*
|
|
219
|
+
* const cms = createClient({
|
|
220
|
+
* sources: { notion: notionSource({ schema, token: process.env.NOTION_TOKEN! }) },
|
|
221
|
+
* ...nodePreset(),
|
|
390
222
|
* });
|
|
223
|
+
*
|
|
224
|
+
* const posts = await cms.posts.list();
|
|
391
225
|
*/
|
|
392
|
-
declare function createClient<
|
|
393
|
-
//#endregion
|
|
394
|
-
//#region src/rendering.d.ts
|
|
395
|
-
/** 本文レンダリングに必要な依存を束ねたコンテキスト。 */
|
|
396
|
-
interface RenderContext<T extends BaseContentItem> {
|
|
397
|
-
source: DataSource<T>;
|
|
398
|
-
rendererFn: RendererFn | undefined;
|
|
399
|
-
imgCache: ImageCacheOps;
|
|
400
|
-
imgCacheName: string;
|
|
401
|
-
hasImageCache: boolean;
|
|
402
|
-
imageProxyBase: string;
|
|
403
|
-
contentConfig: ContentConfig | undefined;
|
|
404
|
-
hooks: CMSHooks<T>;
|
|
405
|
-
logger: Logger | undefined;
|
|
406
|
-
}
|
|
226
|
+
declare function createClient<S extends CMSSources = CMSSources>(opts: CreateClientOptions<S>): CMSClient<MergeSourceCollections<S> extends CollectionsConfig ? MergeSourceCollections<S> : CollectionsConfig>;
|
|
407
227
|
//#endregion
|
|
408
228
|
//#region src/retry.d.ts
|
|
409
229
|
interface RetryConfig {
|
|
@@ -425,69 +245,5 @@ declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
|
425
245
|
*/
|
|
426
246
|
declare function withRetry<T>(fn: () => Promise<T>, config: RetryConfig): Promise<T>;
|
|
427
247
|
//#endregion
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* コレクション別キャッシュキーを生成する。
|
|
431
|
-
* item: `{collection}:{slug}` / list: `{collection}`
|
|
432
|
-
*
|
|
433
|
-
* (Cache adapter 内部のキー戦略はアダプタごとに異なるが、
|
|
434
|
-
* 表示や再計算用に core 側でも公開ヘルパーを提供する)
|
|
435
|
-
*/
|
|
436
|
-
declare function collectionKey(collection: string, slug?: string): string;
|
|
437
|
-
/** 単一コレクションの DataSource + SWR キャッシュ依存を束ねたコンテキスト。 */
|
|
438
|
-
interface CollectionContext<T extends BaseContentItem> {
|
|
439
|
-
collection: string;
|
|
440
|
-
source: DataSource<T>;
|
|
441
|
-
docCache: DocumentCacheOps;
|
|
442
|
-
docCacheName: string;
|
|
443
|
-
render: RenderContext<T>;
|
|
444
|
-
hooks: CMSHooks<T>;
|
|
445
|
-
logger: Logger | undefined;
|
|
446
|
-
ttlMs: number | undefined;
|
|
447
|
-
publishedStatuses: string[];
|
|
448
|
-
accessibleStatuses: string[];
|
|
449
|
-
retryConfig: RetryConfig;
|
|
450
|
-
maxConcurrent: number;
|
|
451
|
-
waitUntil: ((p: Promise<unknown>) => void) | undefined;
|
|
452
|
-
/**
|
|
453
|
-
* slug として使うフィールド名 (CLI 生成の `CollectionDef.slugField`)。
|
|
454
|
-
* `source.properties[slugField].notion` を Notion プロパティ名として
|
|
455
|
-
* `findByProp` を呼び出す。
|
|
456
|
-
*/
|
|
457
|
-
slugField: string;
|
|
458
|
-
}
|
|
459
|
-
/** CollectionClient の実装。ユーザーは `createClient` 経由でインスタンスを受け取る。 */
|
|
460
|
-
declare class CollectionClientImpl<T extends BaseContentItem> implements CollectionClient<T> {
|
|
461
|
-
private readonly ctx;
|
|
462
|
-
readonly cache: CollectionCacheOps<T>;
|
|
463
|
-
constructor(ctx: CollectionContext<T>);
|
|
464
|
-
find(slug: string, opts?: FindOptions): Promise<ItemWithContent<T> | null>;
|
|
465
|
-
list(opts?: ListOptions<T>): Promise<T[]>;
|
|
466
|
-
params(): Promise<string[]>;
|
|
467
|
-
check(slug: string, currentVersion: string): Promise<CheckResult<T> | null>;
|
|
468
|
-
adjacent(slug: string, opts?: AdjacencyOptions<T>): Promise<{
|
|
469
|
-
prev: T | null;
|
|
470
|
-
next: T | null;
|
|
471
|
-
}>;
|
|
472
|
-
private invalidateImpl;
|
|
473
|
-
private invalidateItemImpl;
|
|
474
|
-
private warmImpl;
|
|
475
|
-
private persistMeta;
|
|
476
|
-
private invalidateContentEntry;
|
|
477
|
-
/**
|
|
478
|
-
* 本文キャッシュをロードする。キャッシュが無いか、メタとの整合性が取れない場合は
|
|
479
|
-
* 再生成して書き戻す。
|
|
480
|
-
*/
|
|
481
|
-
private loadOrBuildContent;
|
|
482
|
-
/** メタ既知の状態で本文だけバックグラウンド再生成する。エラーは onSwrError フックに通知する。 */
|
|
483
|
-
private rebuildContentBg;
|
|
484
|
-
private attachLazyContent;
|
|
485
|
-
private fetchList;
|
|
486
|
-
private checkAndUpdateItemBg;
|
|
487
|
-
private checkAndUpdateListBg;
|
|
488
|
-
private fetchListRaw;
|
|
489
|
-
private fetchRaw;
|
|
490
|
-
}
|
|
491
|
-
//#endregion
|
|
492
|
-
export { type AdjacencyOptions, type BaseContentItem, type BuiltInCMSErrorCode, type CMSAdapter, type CMSClient, CMSError, type CMSErrorCode, type CMSErrorContext, type CMSGlobalOps, type CMSHooks, type CMSPlugin, type CMSSchemaProperties, type CMSSources, type CacheAdapter, type CachedItemContent, type CachedItemList, type CachedItemMeta, type CheckResult, type CollectionCacheOps, type CollectionClient, CollectionClientImpl, type CollectionContext, type CollectionDef, type CollectionsConfig, type ContentBlock, type ContentConfig, type ContentResult, type CreateClientOptions, DEFAULT_RETRY_CONFIG, type DataSource, type DocumentCacheOps, type FindOptions, type HandlerAdapter, type HandlerOptions, type ImageCacheOps, type ImageRef, type InferCollectionItem, type InlineNode, type InvalidateKind, type InvalidateScope, type ItemWithContent, type ListOptions, type LogLevel, type Logger, type MaybePromise, type MemoryCacheOptions, type MergeSourceCollections, type PropertyDef, type PropertyMap, type RateLimiterConfig, type RenderOptions, type RendererFn, type RendererPluginList, type RetryConfig, type SWRConfig, type SortOption, type StorageBinary, type WarmOptions, type WarmResult, type WebhookConfig, collectionKey, createClient, createHandler, definePlugin, isCMSError, isCMSErrorInNamespace, isStale, matchCMSError, memoryCache, mergeHooks, mergeLoggers, noopDocOps, noopImgOps, sha256Hex, withRetry };
|
|
248
|
+
export { type AdjacencyOptions, type BaseContentItem, type BuiltInCMSErrorCode, type CMSClient, CMSError, type CMSErrorCode, type CMSErrorContext, type CMSGlobalOps, type CMSHooks, type CMSPlugin, type CMSSchemaProperties, type CMSSources, type CacheAdapter, type CachedItemContent, type CachedItemList, type CachedItemMeta, type CheckResult, type CollectionCacheOps, type CollectionClient, type ContentBlock, type ContentConfig, type ContentResult, type CreateClientOptions, DEFAULT_RETRY_CONFIG, type DataSource, type DocumentCacheOps, type FindOptions, type HandlerAdapter, type HandlerOptions, type ImageCacheOps, type ImageRef, type InlineNode, type InvalidateKind, type InvalidateScope, type ItemWithContent, type ListOptions, type LogLevel, type Logger, type MaybePromise, type MemoryCacheOptions, type NodePresetOptions, type PropertyDef, type PropertyMap, type RateLimiterConfig, type RenderOptions, type RendererFn, type RendererPluginList, type RetryConfig, type SWRConfig, type SortOption, type StorageBinary, type WarmOptions, type WarmResult, type WebhookConfig, createClient, createHandler, definePlugin, isCMSError, isCMSErrorInNamespace, isStale, matchCMSError, memoryCache, mergeHooks, mergeLoggers, nodePreset, noopDocOps, noopImgOps, sha256Hex, withRetry };
|
|
493
249
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { memoryCache } from "./cache/memory.mjs";
|
|
2
2
|
import { CMSError, isCMSError, isCMSErrorInNamespace, matchCMSError } from "./errors.mjs";
|
|
3
3
|
import { mergeHooks, mergeLoggers } from "./hooks.mjs";
|
|
4
|
+
import { nodePreset } from "./preset/node.mjs";
|
|
4
5
|
//#region src/cache.ts
|
|
5
6
|
/** 文字列をSHA-256でハッシュ化し、16進数文字列として返す。画像キーの生成に使用。 */
|
|
6
7
|
async function sha256Hex(input) {
|
|
@@ -159,16 +160,16 @@ function buildCacheImageFn(cache, cacheName, imageProxyBase, logger) {
|
|
|
159
160
|
//#endregion
|
|
160
161
|
//#region src/rendering.ts
|
|
161
162
|
/**
|
|
162
|
-
* `@notion-headless-cms/
|
|
163
|
+
* `@notion-headless-cms/markdown-html` を動的 import してデフォルトレンダラーを返す。
|
|
163
164
|
* core のゼロ依存ルールを守るため静的 import は禁止。
|
|
164
165
|
*/
|
|
165
166
|
async function loadDefaultRenderer() {
|
|
166
167
|
try {
|
|
167
|
-
return (await import("@notion-headless-cms/
|
|
168
|
+
return (await import("@notion-headless-cms/markdown-html")).renderMarkdown;
|
|
168
169
|
} catch {
|
|
169
170
|
throw new CMSError({
|
|
170
171
|
code: "core/config_invalid",
|
|
171
|
-
message: "renderer が未指定で、@notion-headless-cms/
|
|
172
|
+
message: "renderer が未指定で、@notion-headless-cms/markdown-html のロードにも失敗しました。 createClient の renderer オプションを指定するか、@notion-headless-cms/markdown-html をインストールしてください。",
|
|
172
173
|
context: { operation: "loadDefaultRenderer" }
|
|
173
174
|
});
|
|
174
175
|
}
|
|
@@ -322,17 +323,6 @@ async function withRetry(fn, config) {
|
|
|
322
323
|
}
|
|
323
324
|
//#endregion
|
|
324
325
|
//#region src/collection.ts
|
|
325
|
-
/**
|
|
326
|
-
* コレクション別キャッシュキーを生成する。
|
|
327
|
-
* item: `{collection}:{slug}` / list: `{collection}`
|
|
328
|
-
*
|
|
329
|
-
* (Cache adapter 内部のキー戦略はアダプタごとに異なるが、
|
|
330
|
-
* 表示や再計算用に core 側でも公開ヘルパーを提供する)
|
|
331
|
-
*/
|
|
332
|
-
function collectionKey(collection, slug) {
|
|
333
|
-
return slug ? `${collection}:${slug}` : collection;
|
|
334
|
-
}
|
|
335
|
-
/** CollectionClient の実装。ユーザーは `createClient` 経由でインスタンスを受け取る。 */
|
|
336
326
|
var CollectionClientImpl = class {
|
|
337
327
|
cache;
|
|
338
328
|
constructor(ctx) {
|
|
@@ -492,21 +482,17 @@ var CollectionClientImpl = class {
|
|
|
492
482
|
kind: "content"
|
|
493
483
|
});
|
|
494
484
|
}
|
|
495
|
-
/**
|
|
496
|
-
* 本文キャッシュをロードする。キャッシュが無いか、メタとの整合性が取れない場合は
|
|
497
|
-
* 再生成して書き戻す。
|
|
498
|
-
*/
|
|
485
|
+
/** 本文キャッシュ。メタとの整合 (`notionUpdatedAt`) が崩れていれば再生成して書き戻す。 */
|
|
499
486
|
async loadOrBuildContent(slug, item) {
|
|
500
487
|
const expected = this.ctx.source.getLastModified(item);
|
|
501
488
|
const cached = await this.ctx.docCache.getContent(this.ctx.collection, slug);
|
|
502
|
-
|
|
503
|
-
if (cached && cached.notionUpdatedAt === expected && !needsNotionBlocksBackfill) return cached;
|
|
489
|
+
if (cached && cached.notionUpdatedAt === expected) return cached;
|
|
504
490
|
const fresh = await buildCachedItemContent(item, this.ctx.render);
|
|
505
491
|
await this.ctx.docCache.setContent(this.ctx.collection, slug, fresh);
|
|
506
492
|
this.ctx.hooks.onContentRevalidated?.(slug, fresh);
|
|
507
493
|
return fresh;
|
|
508
494
|
}
|
|
509
|
-
/**
|
|
495
|
+
/** メタ既知の状態で本文だけ再生成する。エラーは onSwrError フックに通知して握り潰す。 */
|
|
510
496
|
async rebuildContentBg(slug, item) {
|
|
511
497
|
try {
|
|
512
498
|
const fresh = await buildCachedItemContent(item, this.ctx.render);
|
|
@@ -757,7 +743,7 @@ function applyListOptions(items, opts) {
|
|
|
757
743
|
if (skip > 0 || limit !== void 0) result = result.slice(skip, limit !== void 0 ? skip + limit : void 0);
|
|
758
744
|
return result;
|
|
759
745
|
}
|
|
760
|
-
/** publishedAt
|
|
746
|
+
/** publishedAt 降順 (未設定なら lastEditedTime 降順) でソートする。 */
|
|
761
747
|
function sortByPublishedAtDesc(items) {
|
|
762
748
|
return [...items].sort((a, b) => {
|
|
763
749
|
const av = a.publishedAt ?? a.lastEditedTime;
|
|
@@ -796,10 +782,7 @@ const DEFAULT_OPTS = {
|
|
|
796
782
|
imagesPath: "/images",
|
|
797
783
|
revalidatePath: "/revalidate"
|
|
798
784
|
};
|
|
799
|
-
/**
|
|
800
|
-
* CMSError のコードから HTTP ステータスコードを返す。
|
|
801
|
-
* 既知の webhook エラーコードのみ対応し、それ以外は null を返す。
|
|
802
|
-
*/
|
|
785
|
+
/** Webhook 系の CMSError コードを HTTP ステータスへ写像する。未対応コードは null。 */
|
|
803
786
|
function webhookErrorStatus(code) {
|
|
804
787
|
if (code === "webhook/signature_invalid") return 401;
|
|
805
788
|
if (code === "webhook/not_implemented") return 501;
|
|
@@ -876,10 +859,7 @@ function trimTrailingSlash(s) {
|
|
|
876
859
|
//#region src/cms.ts
|
|
877
860
|
const DEFAULT_IMAGE_PROXY_BASE = "/api/images";
|
|
878
861
|
/**
|
|
879
|
-
* `
|
|
880
|
-
*
|
|
881
|
-
* - 各 adapter の `handles` を見て先勝ち (最初に見つかったもの) で振り分ける
|
|
882
|
-
* - 未指定なら両方 noop
|
|
862
|
+
* adapter の `handles` を見て先勝ちで document / image を割り当てる。未指定は両方 noop。
|
|
883
863
|
*/
|
|
884
864
|
function resolveCache(cache) {
|
|
885
865
|
const adapters = cache ?? [];
|
|
@@ -915,7 +895,6 @@ const LOG_LEVEL_ORDER = {
|
|
|
915
895
|
warn: 2,
|
|
916
896
|
error: 3
|
|
917
897
|
};
|
|
918
|
-
/** `logger` から `minLevel` 未満のレベルを除いた新しい Logger を返す。 */
|
|
919
898
|
function applyLogLevel(logger, minLevel) {
|
|
920
899
|
if (!logger) return void 0;
|
|
921
900
|
const minOrder = LOG_LEVEL_ORDER[minLevel];
|
|
@@ -929,36 +908,31 @@ function applyLogLevel(logger, minLevel) {
|
|
|
929
908
|
return filtered;
|
|
930
909
|
}
|
|
931
910
|
/**
|
|
932
|
-
*
|
|
933
|
-
*
|
|
934
|
-
* 通常はユーザーが直接呼ぶことはなく、CLI 生成の `nhc.ts` の `createClient`
|
|
935
|
-
* (低レベルのこの関数をラップしたもの) を経由する。
|
|
911
|
+
* CMS クライアントを生成する。
|
|
936
912
|
*
|
|
937
913
|
* @example
|
|
938
|
-
* createClient
|
|
939
|
-
*
|
|
940
|
-
*
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
* }
|
|
946
|
-
* },
|
|
947
|
-
* cache: [memoryCache()],
|
|
948
|
-
* swr: { ttlMs: 5 * 60_000 },
|
|
914
|
+
* import { createClient, nodePreset } from "@notion-headless-cms/core";
|
|
915
|
+
* import { notionSource } from "@notion-headless-cms/notion-source";
|
|
916
|
+
* import { schema } from "./generated/nhc.schema";
|
|
917
|
+
*
|
|
918
|
+
* const cms = createClient({
|
|
919
|
+
* sources: { notion: notionSource({ schema, token: process.env.NOTION_TOKEN! }) },
|
|
920
|
+
* ...nodePreset(),
|
|
949
921
|
* });
|
|
922
|
+
*
|
|
923
|
+
* const posts = await cms.posts.list();
|
|
950
924
|
*/
|
|
951
925
|
function createClient(opts) {
|
|
952
|
-
|
|
926
|
+
const collectionsInput = {};
|
|
953
927
|
if (opts.sources) {
|
|
954
|
-
|
|
955
|
-
for (const adapter of Object.values(opts.sources)) if (adapter) Object.assign(mergedFromSources, adapter.collections);
|
|
928
|
+
for (const adapter of Object.values(opts.sources)) if (adapter) Object.assign(collectionsInput, adapter.collections);
|
|
956
929
|
}
|
|
957
|
-
|
|
958
|
-
if (!collectionsInput || Object.keys(collectionsInput).length === 0) throw new CMSError({
|
|
930
|
+
if (Object.keys(collectionsInput).length === 0) throw new CMSError({
|
|
959
931
|
code: "core/config_invalid",
|
|
960
|
-
message: "createClient: sources
|
|
961
|
-
context: { operation: "createClient" }
|
|
932
|
+
message: "createClient: sources に少なくとも 1 つのコレクションを指定してください。",
|
|
933
|
+
context: { operation: "createClient" },
|
|
934
|
+
nextSteps: ["notionSource({ schema, token }) を sources.notion に渡す", "`nhc generate` でスキーマを生成してから import する"],
|
|
935
|
+
docsUrl: "https://github.com/kjfsm/notion-headless-cms/blob/main/docs/quickstart.md"
|
|
962
936
|
});
|
|
963
937
|
for (const [name, def] of Object.entries(collectionsInput)) {
|
|
964
938
|
if (!def.source) throw new CMSError({
|
|
@@ -967,7 +941,8 @@ function createClient(opts) {
|
|
|
967
941
|
context: {
|
|
968
942
|
operation: "createClient",
|
|
969
943
|
collection: name
|
|
970
|
-
}
|
|
944
|
+
},
|
|
945
|
+
nextSteps: ["notionSource(...) を sources に渡しているか確認する"]
|
|
971
946
|
});
|
|
972
947
|
if (!def.slugField) throw new CMSError({
|
|
973
948
|
code: "core/config_invalid",
|
|
@@ -975,7 +950,8 @@ function createClient(opts) {
|
|
|
975
950
|
context: {
|
|
976
951
|
operation: "createClient",
|
|
977
952
|
collection: name
|
|
978
|
-
}
|
|
953
|
+
},
|
|
954
|
+
nextSteps: [`nhc.config.ts の ${name} コレクションに slugField を設定する`]
|
|
979
955
|
});
|
|
980
956
|
}
|
|
981
957
|
const cacheRes = resolveCache(opts.cache);
|
|
@@ -1080,6 +1056,6 @@ function definePlugin(plugin) {
|
|
|
1080
1056
|
return plugin;
|
|
1081
1057
|
}
|
|
1082
1058
|
//#endregion
|
|
1083
|
-
export { CMSError,
|
|
1059
|
+
export { CMSError, DEFAULT_RETRY_CONFIG, createClient, createHandler, definePlugin, isCMSError, isCMSErrorInNamespace, isStale, matchCMSError, memoryCache, mergeHooks, mergeLoggers, nodePreset, noopDocOps, noopImgOps, sha256Hex, withRetry };
|
|
1084
1060
|
|
|
1085
1061
|
//# sourceMappingURL=index.mjs.map
|