@notion-headless-cms/core 0.1.1 → 0.1.2

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,26 @@
1
+ // src/errors.ts
2
+ var CMSError = class extends Error {
3
+ code;
4
+ cause;
5
+ context;
6
+ constructor(params) {
7
+ super(params.message, { cause: params.cause });
8
+ this.name = "CMSError";
9
+ this.code = params.code;
10
+ this.cause = params.cause;
11
+ this.context = params.context;
12
+ }
13
+ };
14
+ function isCMSError(error) {
15
+ return error instanceof CMSError;
16
+ }
17
+ function isCMSErrorInNamespace(error, namespace) {
18
+ return isCMSError(error) && error.code.startsWith(namespace);
19
+ }
20
+
21
+ export {
22
+ CMSError,
23
+ isCMSError,
24
+ isCMSErrorInNamespace
25
+ };
26
+ //# sourceMappingURL=chunk-V6ML4QE5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts"],"sourcesContent":["type BuiltInCMSErrorCode =\n\t| \"core/config_invalid\"\n\t| \"core/schema_invalid\"\n\t| \"source/fetch_items_failed\"\n\t| \"source/fetch_item_failed\"\n\t| \"source/load_markdown_failed\"\n\t| \"cache/io_failed\"\n\t| \"cache/image_fetch_failed\"\n\t| \"renderer/failed\";\n\n/**\n * CMS エラーコード。\n * `BuiltInCMSErrorCode` のリテラル補完を維持しつつ、\n * サードパーティアダプタが独自コードを定義できるよう `string & {}` で拡張可能にする。\n */\nexport type CMSErrorCode = BuiltInCMSErrorCode | (string & {});\n\nexport interface CMSErrorContext {\n\toperation: string;\n\tslug?: string;\n\tdataSourceId?: string;\n\tpageId?: string;\n\t[key: string]: string | number | boolean | null | undefined;\n}\n\nexport class CMSError extends Error {\n\treadonly code: CMSErrorCode;\n\toverride readonly cause?: unknown;\n\treadonly context: CMSErrorContext;\n\n\tconstructor(params: {\n\t\tcode: CMSErrorCode;\n\t\tmessage: string;\n\t\tcause?: unknown;\n\t\tcontext: CMSErrorContext;\n\t}) {\n\t\tsuper(params.message, { cause: params.cause });\n\t\tthis.name = \"CMSError\";\n\t\tthis.code = params.code;\n\t\tthis.cause = params.cause;\n\t\tthis.context = params.context;\n\t}\n}\n\nexport function isCMSError(error: unknown): error is CMSError {\n\treturn error instanceof CMSError;\n}\n\n/** エラーコードが特定の名前空間に属するかを判定する(例: \"source/\")。 */\nexport function isCMSErrorInNamespace(\n\terror: unknown,\n\tnamespace: string,\n): error is CMSError {\n\treturn isCMSError(error) && error.code.startsWith(namespace);\n}\n"],"mappings":";AAyBO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAC1B;AAAA,EACS;AAAA,EACT;AAAA,EAET,YAAY,QAKT;AACF,UAAM,OAAO,SAAS,EAAE,OAAO,OAAO,MAAM,CAAC;AAC7C,SAAK,OAAO;AACZ,SAAK,OAAO,OAAO;AACnB,SAAK,QAAQ,OAAO;AACpB,SAAK,UAAU,OAAO;AAAA,EACvB;AACD;AAEO,SAAS,WAAW,OAAmC;AAC7D,SAAO,iBAAiB;AACzB;AAGO,SAAS,sBACf,OACA,WACoB;AACpB,SAAO,WAAW,KAAK,KAAK,MAAM,KAAK,WAAW,SAAS;AAC5D;","names":[]}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * ライブラリが動作するために必須なフィールド。
3
+ * 利用者はこのインターフェースを拡張して独自のコンテンツ型を定義する。
4
+ *
5
+ * @example
6
+ * interface Post extends BaseContentItem {
7
+ * title: string;
8
+ * author: string;
9
+ * }
10
+ * createCMS<Post>({ source: notionAdapter({ ... }) })
11
+ */
12
+ interface BaseContentItem {
13
+ /** Notion ページ ID(変更検知に必須)。 */
14
+ id: string;
15
+ /** URL キー(必須)。 */
16
+ slug: string;
17
+ /** 最終更新タイムスタンプ(変更検知に必須)。 */
18
+ updatedAt: string;
19
+ /** コンテンツのステータス。ステータスのない DB では省略可能。 */
20
+ status?: string;
21
+ /** 公開日時。日付プロパティのない DB では省略可能。 */
22
+ publishedAt?: string;
23
+ }
24
+ /** ストレージにキャッシュされたレンダリング済みコンテンツ。 */
25
+ interface CachedItem<T extends BaseContentItem = BaseContentItem> {
26
+ html: string;
27
+ item: T;
28
+ notionUpdatedAt: string;
29
+ cachedAt: number;
30
+ }
31
+ /** ストレージにキャッシュされたコンテンツ一覧。 */
32
+ interface CachedItemList<T extends BaseContentItem = BaseContentItem> {
33
+ items: T[];
34
+ cachedAt: number;
35
+ }
36
+ /** ストレージから取得したバイナリオブジェクト。 */
37
+ interface StorageBinary {
38
+ data: ArrayBuffer;
39
+ contentType?: string;
40
+ }
41
+ /** Notionのプロパティ名マッピング(すべてオプション)。 */
42
+ interface CMSSchemaProperties {
43
+ /** Notionのスラッグプロパティ名。デフォルト: 'Slug' */
44
+ slug?: string;
45
+ /** Notionのステータスプロパティ名。デフォルト: 'Status' */
46
+ status?: string;
47
+ /** Notionの公開日プロパティ名。デフォルト: 'CreatedAt' */
48
+ date?: string;
49
+ }
50
+
51
+ export type { BaseContentItem as B, CMSSchemaProperties as C, StorageBinary as S, CachedItem as a, CachedItemList as b };
@@ -0,0 +1,30 @@
1
+ type BuiltInCMSErrorCode = "core/config_invalid" | "core/schema_invalid" | "source/fetch_items_failed" | "source/fetch_item_failed" | "source/load_markdown_failed" | "cache/io_failed" | "cache/image_fetch_failed" | "renderer/failed";
2
+ /**
3
+ * CMS エラーコード。
4
+ * `BuiltInCMSErrorCode` のリテラル補完を維持しつつ、
5
+ * サードパーティアダプタが独自コードを定義できるよう `string & {}` で拡張可能にする。
6
+ */
7
+ type CMSErrorCode = BuiltInCMSErrorCode | (string & {});
8
+ interface CMSErrorContext {
9
+ operation: string;
10
+ slug?: string;
11
+ dataSourceId?: string;
12
+ pageId?: string;
13
+ [key: string]: string | number | boolean | null | undefined;
14
+ }
15
+ declare class CMSError extends Error {
16
+ readonly code: CMSErrorCode;
17
+ readonly cause?: unknown;
18
+ readonly context: CMSErrorContext;
19
+ constructor(params: {
20
+ code: CMSErrorCode;
21
+ message: string;
22
+ cause?: unknown;
23
+ context: CMSErrorContext;
24
+ });
25
+ }
26
+ declare function isCMSError(error: unknown): error is CMSError;
27
+ /** エラーコードが特定の名前空間に属するかを判定する(例: "source/")。 */
28
+ declare function isCMSErrorInNamespace(error: unknown, namespace: string): error is CMSError;
29
+
30
+ export { CMSError, type CMSErrorCode, type CMSErrorContext, isCMSError, isCMSErrorInNamespace };
package/dist/errors.js ADDED
@@ -0,0 +1,11 @@
1
+ import {
2
+ CMSError,
3
+ isCMSError,
4
+ isCMSErrorInNamespace
5
+ } from "./chunk-V6ML4QE5.js";
6
+ export {
7
+ CMSError,
8
+ isCMSError,
9
+ isCMSErrorInNamespace
10
+ };
11
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,41 @@
1
+ import { B as BaseContentItem, a as CachedItem } from './content-Biqf0l_o.js';
2
+
3
+ type MaybePromise<T> = T | Promise<T>;
4
+ interface CMSHooks<T extends BaseContentItem = BaseContentItem> {
5
+ beforeCache?: (item: CachedItem<T>) => MaybePromise<CachedItem<T>>;
6
+ afterRender?: (html: string, item: T) => MaybePromise<string>;
7
+ onCacheHit?: (slug: string, item: CachedItem<T>) => void;
8
+ onCacheMiss?: (slug: string) => void;
9
+ onListCacheHit?: (items: T[], cachedAt: number) => void;
10
+ onListCacheMiss?: () => void;
11
+ onError?: (error: Error) => void;
12
+ onRenderStart?: (slug: string) => void;
13
+ onRenderEnd?: (slug: string, durationMs: number) => void;
14
+ }
15
+
16
+ interface Logger {
17
+ debug?: (message: string, context?: Record<string, unknown>) => void;
18
+ info?: (message: string, context?: Record<string, unknown>) => void;
19
+ warn?: (message: string, context?: Record<string, unknown>) => void;
20
+ error?: (message: string, context?: Record<string, unknown>) => void;
21
+ }
22
+
23
+ interface CMSPlugin<T extends BaseContentItem = BaseContentItem> {
24
+ name: string;
25
+ hooks?: CMSHooks<T>;
26
+ logger?: Partial<Logger>;
27
+ }
28
+ declare function definePlugin<T extends BaseContentItem>(plugin: CMSPlugin<T>): CMSPlugin<T>;
29
+
30
+ /**
31
+ * プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。
32
+ * beforeCache / afterRender はパイプライン(前の出力が次の入力)。
33
+ * onCacheHit などオブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。
34
+ */
35
+ declare function mergeHooks<T extends BaseContentItem>(plugins: CMSPlugin<T>[], directHooks?: CMSHooks<T>, logger?: Logger): CMSHooks<T>;
36
+ /** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */
37
+ declare function mergeLoggers(plugins: Array<{
38
+ logger?: Partial<Logger>;
39
+ }>, directLogger?: Logger): Logger | undefined;
40
+
41
+ export { type CMSHooks as C, type Logger as L, type MaybePromise as M, type CMSPlugin as a, mergeLoggers as b, definePlugin as d, mergeHooks as m };
@@ -0,0 +1,2 @@
1
+ import './content-Biqf0l_o.js';
2
+ export { m as mergeHooks, b as mergeLoggers } from './hooks-B83RUclt.js';
package/dist/hooks.js ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ mergeHooks,
3
+ mergeLoggers
4
+ } from "./chunk-4KGKWKKI.js";
5
+ export {
6
+ mergeHooks,
7
+ mergeLoggers
8
+ };
9
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,13 @@
1
- import { RendererFn } from '@notion-headless-cms/renderer';
2
- import { BlockHandler } from '@notion-headless-cms/transformer';
3
- import { PageObjectResponse, RichTextItemResponse } from '@notionhq/client/build/src/api-endpoints';
4
- import { PluggableList } from 'unified';
1
+ export { MemoryDocumentCacheOptions, MemoryImageCacheOptions, memoryCache, memoryDocumentCache, memoryImageCache } from './cache/memory.js';
2
+ export { noopDocumentCache, noopImageCache } from './cache/noop.js';
3
+ import { B as BaseContentItem, C as CMSSchemaProperties, a as CachedItem, S as StorageBinary } from './content-Biqf0l_o.js';
4
+ export { b as CachedItemList } from './content-Biqf0l_o.js';
5
+ import { PluggableList } from '@notion-headless-cms/renderer';
6
+ import { C as CacheConfig } from './cache-DvbyemBK.js';
7
+ export { D as DocumentCacheAdapter, I as ImageCacheAdapter } from './cache-DvbyemBK.js';
8
+ import { C as CMSHooks, a as CMSPlugin, L as Logger } from './hooks-B83RUclt.js';
9
+ export { M as MaybePromise, d as definePlugin, m as mergeHooks, b as mergeLoggers } from './hooks-B83RUclt.js';
10
+ export { CMSError, CMSErrorCode, CMSErrorContext, isCMSError, isCMSErrorInNamespace } from './errors.js';
5
11
 
6
12
  /** 文字列をSHA-256でハッシュ化し、16進数文字列として返す。画像キーの生成に使用。 */
7
13
  declare function sha256Hex(input: string): Promise<string>;
@@ -11,103 +17,6 @@ declare function sha256Hex(input: string): Promise<string>;
11
17
  */
12
18
  declare function isStale(cachedAt: number, ttlMs?: number): boolean;
13
19
 
14
- /**
15
- * ライブラリが動作するために必須なフィールド。
16
- * 利用者はこのインターフェースを拡張して独自のコンテンツ型を定義する。
17
- *
18
- * @example
19
- * interface Post extends BaseContentItem {
20
- * title: string;
21
- * author: string;
22
- * }
23
- * createCMS<Post>({ source: notionAdapter({ ... }) })
24
- */
25
- interface BaseContentItem {
26
- id: string;
27
- slug: string;
28
- status: string;
29
- publishedAt: string;
30
- updatedAt: string;
31
- }
32
- /** ストレージにキャッシュされたレンダリング済みコンテンツ。 */
33
- interface CachedItem<T extends BaseContentItem = BaseContentItem> {
34
- html: string;
35
- item: T;
36
- notionUpdatedAt: string;
37
- cachedAt: number;
38
- }
39
- /** ストレージにキャッシュされたコンテンツ一覧。 */
40
- interface CachedItemList<T extends BaseContentItem = BaseContentItem> {
41
- items: T[];
42
- cachedAt: number;
43
- }
44
- /** ストレージから取得したバイナリオブジェクト。 */
45
- interface StorageBinary {
46
- data: ArrayBuffer;
47
- contentType?: string;
48
- }
49
- /** Notionのプロパティ名マッピング(すべてオプション)。 */
50
- interface CMSSchemaProperties {
51
- /** Notionのスラッグプロパティ名。デフォルト: 'Slug' */
52
- slug?: string;
53
- /** Notionのステータスプロパティ名。デフォルト: 'Status' */
54
- status?: string;
55
- /** Notionの公開日プロパティ名。デフォルト: 'CreatedAt' */
56
- date?: string;
57
- }
58
-
59
- /** ドキュメントキャッシュを抽象化するインターフェース。 */
60
- interface DocumentCacheAdapter<T extends BaseContentItem = BaseContentItem> {
61
- readonly name: string;
62
- getList(): Promise<CachedItemList<T> | null>;
63
- setList(data: CachedItemList<T>): Promise<void>;
64
- getItem(slug: string): Promise<CachedItem<T> | null>;
65
- setItem(slug: string, data: CachedItem<T>): Promise<void>;
66
- invalidate?(scope: "all" | {
67
- slug: string;
68
- } | {
69
- tag: string;
70
- }): Promise<void>;
71
- }
72
- /** 画像キャッシュを抽象化するインターフェース。 */
73
- interface ImageCacheAdapter {
74
- readonly name: string;
75
- get(hash: string): Promise<StorageBinary | null>;
76
- set(hash: string, data: ArrayBuffer, contentType: string): Promise<void>;
77
- }
78
- /** キャッシュ設定オブジェクト。document / image それぞれ独立したアダプタを差し込める。 */
79
- interface CacheConfig<T extends BaseContentItem = BaseContentItem> {
80
- document?: DocumentCacheAdapter<T> | false;
81
- image?: ImageCacheAdapter | false;
82
- /** キャッシュの有効期間(ミリ秒)。未設定の場合はTTLなし。 */
83
- ttlMs?: number;
84
- }
85
-
86
- type MaybePromise<T> = T | Promise<T>;
87
- interface CMSHooks<T extends BaseContentItem = BaseContentItem> {
88
- beforeCache?: (item: CachedItem<T>) => MaybePromise<CachedItem<T>>;
89
- afterRender?: (html: string, item: T) => MaybePromise<string>;
90
- onCacheHit?: (slug: string, item: CachedItem<T>) => void;
91
- onCacheMiss?: (slug: string) => void;
92
- onListCacheHit?: (items: T[], cachedAt: number) => void;
93
- onListCacheMiss?: () => void;
94
- onError?: (error: Error) => void;
95
- }
96
-
97
- interface Logger {
98
- debug?: (message: string, context?: Record<string, unknown>) => void;
99
- info?: (message: string, context?: Record<string, unknown>) => void;
100
- warn?: (message: string, context?: Record<string, unknown>) => void;
101
- error?: (message: string, context?: Record<string, unknown>) => void;
102
- }
103
-
104
- interface CMSPlugin<T extends BaseContentItem = BaseContentItem> {
105
- name: string;
106
- hooks?: CMSHooks<T>;
107
- logger?: Partial<Logger>;
108
- }
109
- declare function definePlugin<T extends BaseContentItem>(plugin: CMSPlugin<T>): CMSPlugin<T>;
110
-
111
20
  /** ソース側クエリのフィルタ・ソート条件。 */
112
21
  interface SourceQueryOptions {
113
22
  filter?: {
@@ -145,19 +54,26 @@ interface DataSourceAdapter<T extends BaseContentItem = BaseContentItem> {
145
54
  query?(opts: SourceQueryOptions): Promise<SourceQueryResult<T>>;
146
55
  }
147
56
 
57
+ /**
58
+ * render() オプション。core は renderer の実装を知らず、この型だけを扱う。
59
+ * @notion-headless-cms/renderer の renderMarkdown() はこのシグネチャと構造的に互換。
60
+ */
61
+ interface RenderOptions {
62
+ imageProxyBase?: string;
63
+ cacheImage?: (url: string) => Promise<string>;
64
+ remarkPlugins?: PluggableList;
65
+ rehypePlugins?: PluggableList;
66
+ }
67
+ /** カスタムレンダラー関数の型。デフォルトは @notion-headless-cms/renderer の renderMarkdown。 */
68
+ type RendererFn = (markdown: string, opts?: RenderOptions) => Promise<string>;
148
69
  /** スキーマ設定。公開ステータスのフィルタやプロパティ名マッピングを制御する。 */
149
70
  interface SchemaConfig<T extends BaseContentItem = BaseContentItem> {
150
- /**
151
- * Notionページをコンテンツ型 T にマッピングするカスタム関数。
152
- * 指定した場合 properties の設定は無視される(slug プロパティ名のみ例外)。
153
- */
154
- mapItem?: (page: PageObjectResponse) => T;
155
- /** mapItem 未使用時のプロパティ名マッピング。 */
156
- properties?: CMSSchemaProperties;
157
71
  /** list() で返す「公開済み」ステータス値の配列。デフォルト: [] (全件返す) */
158
72
  publishedStatuses?: string[];
159
73
  /** findBySlug() でアクセス可能なステータス値の配列。デフォルト: [] (全件許可) */
160
74
  accessibleStatuses?: string[];
75
+ /** mapItem 未使用時のプロパティ名マッピング。source-notion 経由で渡す場合は不要。 */
76
+ properties?: CMSSchemaProperties;
161
77
  }
162
78
  /** レンダリング・コンテンツ処理設定。 */
163
79
  interface ContentConfig {
@@ -167,10 +83,6 @@ interface ContentConfig {
167
83
  remarkPlugins?: PluggableList;
168
84
  /** 追加する rehype プラグイン。 */
169
85
  rehypePlugins?: PluggableList;
170
- /** デフォルトのパイプラインを置き換えるカスタムレンダラー。 */
171
- render?: RendererFn;
172
- /** カスタムブロックハンドラーのマップ。Notionブロックタイプをキーとする。 */
173
- blocks?: Record<string, BlockHandler>;
174
86
  }
175
87
  /** レートリミット・リトライ設定。 */
176
88
  interface RateLimiterConfig {
@@ -190,6 +102,8 @@ interface RateLimiterConfig {
190
102
  interface CreateCMSOptions<T extends BaseContentItem = BaseContentItem> {
191
103
  /** データソースアダプタ(Notion など)。 */
192
104
  source: DataSourceAdapter<T>;
105
+ /** レンダラー関数。未指定時は @notion-headless-cms/renderer の renderMarkdown を使用。 */
106
+ renderer?: RendererFn;
193
107
  /** キャッシュ設定。未設定時はキャッシュなし。 */
194
108
  cache?: CacheConfig<T>;
195
109
  /** スキーマ・ステータス設定。 */
@@ -208,21 +122,6 @@ interface CreateCMSOptions<T extends BaseContentItem = BaseContentItem> {
208
122
  rateLimiter?: RateLimiterConfig;
209
123
  }
210
124
 
211
- /** インメモリキャッシュ(ドキュメント用)を生成する。 */
212
- declare function memoryDocumentCache<T extends BaseContentItem = BaseContentItem>(): DocumentCacheAdapter<T>;
213
- /** インメモリキャッシュ(画像用)を生成する。 */
214
- declare function memoryImageCache(): ImageCacheAdapter;
215
- /**
216
- * ドキュメントと画像の両方にインメモリキャッシュを返す便利関数。
217
- * memoryCache() はドキュメントキャッシュを返す(後方互換)。
218
- */
219
- declare function memoryCache<T extends BaseContentItem = BaseContentItem>(): DocumentCacheAdapter<T>;
220
-
221
- /** 何もしないドキュメントキャッシュを返す(シングルトン)。 */
222
- declare function noopDocumentCache<T extends BaseContentItem = BaseContentItem>(): DocumentCacheAdapter<T>;
223
- /** 何もしない画像キャッシュを返す(シングルトン)。 */
224
- declare function noopImageCache(): ImageCacheAdapter;
225
-
226
125
  interface QueryResult<T> {
227
126
  items: T[];
228
127
  total: number;
@@ -252,23 +151,26 @@ declare class QueryBuilder<T extends BaseContentItem> {
252
151
  }): this;
253
152
  execute(): Promise<QueryResult<T>>;
254
153
  executeOne(): Promise<T | null>;
154
+ /** 前後アイテムを返す。sortBy() で指定したソート順を適用する。 */
255
155
  adjacent(slug: string): Promise<{
256
156
  prev: T | null;
257
157
  next: T | null;
258
158
  }>;
159
+ /** 最初の 1 件を返す。`.paginate({ page: 1, perPage: 1 }).executeOne()` の短縮形。 */
160
+ first(): Promise<T | null>;
259
161
  }
260
162
 
261
- /** キャッシュ優先アクセサ。 */
262
- interface CachedAccessor<T extends BaseContentItem> {
263
- list(): Promise<{
163
+ /** キャッシュ系の公開名前空間。SWR 読み取りとキャッシュ管理を統合する。 */
164
+ interface CacheAccessor<T extends BaseContentItem> {
165
+ /** キャッシュ優先でコンテンツ一覧を返す(SWR)。 */
166
+ getList(): Promise<{
264
167
  items: T[];
265
168
  isStale: boolean;
266
169
  cachedAt: number;
267
170
  }>;
171
+ /** キャッシュ優先で単一コンテンツを返す(SWR)。HTML 付きの CachedItem を返す。 */
268
172
  get(slug: string): Promise<CachedItem<T> | null>;
269
- }
270
- /** キャッシュ管理オペレーション。 */
271
- interface CacheManager<T extends BaseContentItem> {
173
+ /** 全コンテンツを事前レンダリングしてキャッシュに保存する。 */
272
174
  prefetchAll(opts?: {
273
175
  concurrency?: number;
274
176
  onProgress?: (done: number, total: number) => void;
@@ -276,20 +178,24 @@ interface CacheManager<T extends BaseContentItem> {
276
178
  ok: number;
277
179
  failed: number;
278
180
  }>;
181
+ /** 指定スコープのキャッシュを無効化する。 */
279
182
  revalidate(scope?: "all" | {
280
183
  slug: string;
281
184
  }): Promise<void>;
185
+ /** Webhook ペイロードを元にキャッシュを同期する。 */
282
186
  sync(payload?: {
283
187
  slug?: string;
284
188
  }): Promise<{
285
189
  updated: string[];
286
190
  }>;
191
+ /** リスト全体の変更を検知する。version はリスト取得時の buildListVersion の値。 */
287
192
  checkList(version: string): Promise<{
288
193
  changed: false;
289
194
  } | {
290
195
  changed: true;
291
196
  items: T[];
292
197
  }>;
198
+ /** 単一アイテムの変更を検知し、変更があれば再レンダリングしてキャッシュを更新する。 */
293
199
  checkItem(slug: string, lastEdited: string): Promise<{
294
200
  changed: false;
295
201
  } | {
@@ -307,6 +213,7 @@ interface CacheManager<T extends BaseContentItem> {
307
213
  * source: notionAdapter({ token: '...', dataSourceId: '...' }),
308
214
  * });
309
215
  * const items = await cms.list();
216
+ * const entry = await cms.cache.get('my-post');
310
217
  */
311
218
  declare class CMS<T extends BaseContentItem = BaseContentItem> {
312
219
  private readonly source;
@@ -318,157 +225,54 @@ declare class CMS<T extends BaseContentItem = BaseContentItem> {
318
225
  private readonly accessibleStatuses;
319
226
  private readonly imageProxyBase;
320
227
  private readonly contentConfig;
228
+ private readonly rendererFn;
321
229
  private readonly waitUntil;
322
230
  private readonly hooks;
323
231
  private readonly logger;
324
232
  private readonly retryConfig;
325
- readonly cached: CachedAccessor<T>;
326
- readonly cache: CacheManager<T>;
233
+ private readonly maxConcurrent;
234
+ readonly cache: CacheAccessor<T>;
327
235
  constructor(opts: CreateCMSOptions<T>);
328
236
  /** 公開済みコンテンツ一覧をソースから直接取得する。 */
329
237
  list(): Promise<T[]>;
330
238
  /** スラッグでコンテンツをソースから直接取得する。 */
331
239
  find(slug: string): Promise<T | null>;
332
- /** @deprecated find() を使用してください。 */
333
- findBySlug(slug: string): Promise<T | null>;
240
+ /** 複数スラッグをまとめてソースから直接取得する。accessibleStatuses フィルタを適用する。 */
241
+ findMany(slugs: string[]): Promise<Map<string, T>>;
334
242
  /** アイテムが publishedStatuses に含まれるステータスかどうかを返す。 */
335
243
  isPublished(item: T): boolean;
336
- /** コンテンツを Markdown → HTML にレンダリングし、CachedItem として返す。 */
244
+ /** コンテンツを Markdown → HTML にレンダリングし、CachedItem として返す。キャッシュには保存しない。 */
337
245
  render(item: T): Promise<CachedItem<T>>;
338
246
  /** QueryBuilder を返す。ステータス・タグ・ページネーションなどを連鎖で指定できる。 */
339
247
  query(): QueryBuilder<T>;
340
- /** 全コンテンツを事前レンダリングしてキャッシュに保存する。 */
341
- prefetchAll(opts?: {
342
- concurrency?: number;
343
- onProgress?: (done: number, total: number) => void;
344
- }): Promise<{
345
- ok: number;
346
- failed: number;
347
- }>;
348
248
  /** 静的生成用のスラッグ一覧を返す。 */
349
249
  getStaticSlugs(): Promise<string[]>;
350
- /** 指定スコープのキャッシュを無効化する。 */
351
- revalidate(scope?: "all" | {
352
- slug: string;
353
- }): Promise<void>;
354
- /** Webhook ペイロードを元にキャッシュを同期する。 */
355
- syncFromWebhook(payload?: {
356
- slug?: string;
357
- }): Promise<{
358
- updated: string[];
359
- }>;
360
- /** キャッシュ優先でコンテンツ一覧を返す(SWR)。 */
361
- private cachedList;
362
- /** キャッシュ優先で単一コンテンツを返す(SWR)。 */
363
- private cachedGet;
364
- checkListUpdate(version: string): Promise<{
365
- changed: false;
366
- } | {
367
- changed: true;
368
- items: T[];
369
- }>;
370
- checkItemUpdate(slug: string, lastEdited: string): Promise<{
371
- changed: false;
372
- } | {
373
- changed: true;
374
- html: string;
375
- item: T;
376
- notionUpdatedAt: string;
377
- }>;
378
- /** @deprecated cached.list() を使用してください。 */
379
- getList(): Promise<{
380
- items: T[];
381
- listVersion: string;
382
- }>;
383
- /** @deprecated cached.get() を使用してください。 */
384
- getItem(slug: string): Promise<CachedItem<T> | null>;
385
- /** @deprecated cache.prefetchAll() を使用してください。 */
386
- prefetchAllLegacy(opts?: {
387
- concurrency?: number;
388
- onProgress?: (done: number, total: number) => void;
389
- }): Promise<{
390
- ok: number;
391
- failed: number;
392
- }>;
393
- /** @deprecated query().status(s).execute() を使用してください。 */
394
- listByStatus(status: string | readonly string[]): Promise<T[]>;
395
- /** @deprecated query().where(pred).execute() を使用してください。 */
396
- where(predicate: (item: T) => boolean): Promise<T[]>;
397
- /** @deprecated query().paginate(opts).execute() を使用してください。 */
398
- paginate(opts: {
399
- page: number;
400
- perPage: number;
401
- }): Promise<{
402
- items: T[];
403
- total: number;
404
- page: number;
405
- perPage: number;
406
- hasNext: boolean;
407
- }>;
408
- /** @deprecated query().adjacent(slug) を使用してください。 */
409
- getAdjacent(slug: string): Promise<{
410
- prev: T | null;
411
- next: T | null;
412
- }>;
413
250
  /** ハッシュキーでキャッシュ画像を取得する。 */
414
251
  getCachedImage(hash: string): Promise<StorageBinary | null>;
415
252
  /** ハッシュキーでキャッシュ画像を Response として返す。 */
416
253
  createCachedImageResponse(hash: string): Promise<Response | null>;
254
+ private cachedList;
255
+ private cachedGet;
256
+ private prefetchAll;
257
+ private revalidate;
258
+ private syncFromWebhook;
259
+ private checkListUpdate;
260
+ private checkItemUpdate;
417
261
  private buildCachedItem;
418
262
  }
419
263
  /** 設定済みの CMS インスタンスを生成するファクトリ関数。 */
420
264
  declare function createCMS<T extends BaseContentItem = BaseContentItem>(opts: CreateCMSOptions<T>): CMS<T>;
421
265
 
422
- type CMSErrorCode = "CONFIG_INVALID" | "NOTION_ITEM_SCHEMA_INVALID" | "NOTION_FETCH_ITEMS_FAILED" | "NOTION_FETCH_ITEM_BY_SLUG_FAILED" | "NOTION_GET_BLOCKS_FAILED" | "NOTION_MARKDOWN_FETCH_FAILED" | "IMAGE_CACHE_FAILED" | "RENDERER_FAILED";
423
- interface CMSErrorContext {
424
- operation: string;
425
- slug?: string;
426
- dataSourceId?: string;
427
- pageId?: string;
428
- [key: string]: string | number | boolean | null | undefined;
429
- }
430
- declare class CMSError extends Error {
431
- readonly code: CMSErrorCode;
432
- readonly cause?: unknown;
433
- readonly context: CMSErrorContext;
434
- constructor(params: {
435
- code: CMSErrorCode;
436
- message: string;
437
- cause?: unknown;
438
- context: CMSErrorContext;
439
- });
440
- }
441
- declare function isCMSError(error: unknown): error is CMSError;
442
-
443
- /**
444
- * プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。
445
- * beforeCache / afterRender はパイプライン(前の出力が次の入力)。
446
- * onCacheHit などオブザーバー系は全員に同じ値を渡す。
447
- */
448
- declare function mergeHooks<T extends BaseContentItem>(plugins: CMSPlugin<T>[], directHooks?: CMSHooks<T>): CMSHooks<T>;
449
- /** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */
450
- declare function mergeLoggers(plugins: Array<{
451
- logger?: Partial<Logger>;
452
- }>, directLogger?: Logger): Logger | undefined;
453
-
454
- /** Notionリッチテキスト配列をプレーンテキストに結合する。 */
455
- declare function getPlainText(items: RichTextItemResponse[] | undefined): string;
456
- /**
457
- * NotionのPageObjectResponseをデフォルトの BaseContentItem に変換する。
458
- * 独自の拡張型(title などを含む)が必要な場合は、本関数の戻り値に
459
- * 追加フィールドを足してカスタム mapItem を実装する。
460
- */
461
- declare function mapItem(page: PageObjectResponse, props: Required<CMSSchemaProperties>): BaseContentItem;
462
-
463
266
  interface RetryConfig {
464
- maxConcurrent: number;
465
267
  retryOn: number[];
466
268
  maxRetries: number;
467
269
  baseDelayMs: number;
270
+ /** true のとき指数バックオフにランダムジッターを加える(Thundering Herd 対策)。デフォルト: true */
271
+ jitter?: boolean;
468
272
  onRetry?: (attempt: number, status: number) => void;
469
273
  }
470
274
  declare const DEFAULT_RETRY_CONFIG: RetryConfig;
471
- /** 指数バックオフでリトライする。retryOn に含まれる HTTP エラーのみ対象。 */
275
+ /** 指数バックオフ(オプションでジッター付き)でリトライする。retryOn に含まれる HTTP エラーのみ対象。 */
472
276
  declare function withRetry<T>(fn: () => Promise<T>, config: RetryConfig): Promise<T>;
473
277
 
474
- export { type BaseContentItem, CMS, CMSError, type CMSErrorCode, type CMSErrorContext, type CMSHooks, type CMSPlugin, type CMSSchemaProperties, type CacheConfig, type CachedItem, type CachedItemList, type ContentConfig, type CreateCMSOptions, DEFAULT_RETRY_CONFIG, type DataSourceAdapter, type DocumentCacheAdapter, type ImageCacheAdapter, type Logger, type MaybePromise, QueryBuilder, type QueryResult, type RateLimiterConfig, type RetryConfig, type SchemaConfig, type SourceQueryOptions, type SourceQueryResult, type StorageBinary, createCMS, definePlugin, getPlainText, isCMSError, isStale, mapItem, memoryCache, memoryDocumentCache, memoryImageCache, mergeHooks, mergeLoggers, noopDocumentCache, noopImageCache, sha256Hex, withRetry };
278
+ export { BaseContentItem, CMS, CMSHooks, CMSPlugin, CMSSchemaProperties, type CacheAccessor, CacheConfig, CachedItem, type ContentConfig, type CreateCMSOptions, DEFAULT_RETRY_CONFIG, type DataSourceAdapter, Logger, QueryBuilder, type QueryResult, type RateLimiterConfig, type RenderOptions, type RendererFn, type RetryConfig, type SchemaConfig, type SourceQueryOptions, type SourceQueryResult, StorageBinary, createCMS, isStale, sha256Hex, withRetry };