@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/README.md
CHANGED
package/dist/cache/memory.d.mts
CHANGED
|
@@ -1,2 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { t as CacheAdapter } from "../cache-DS81aOcC.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/cache/memory.d.ts
|
|
4
|
+
interface MemoryDocumentOptions {
|
|
5
|
+
/** アイテム保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
6
|
+
maxItems?: number;
|
|
7
|
+
}
|
|
8
|
+
interface MemoryImageOptions {
|
|
9
|
+
/** エントリ保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
10
|
+
maxItems?: number;
|
|
11
|
+
/** 合計保持サイズ上限(バイト)。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
12
|
+
maxSizeBytes?: number;
|
|
13
|
+
}
|
|
14
|
+
interface MemoryCacheOptions extends MemoryDocumentOptions, MemoryImageOptions {}
|
|
15
|
+
/**
|
|
16
|
+
* インメモリのキャッシュアダプタ。document + image 両方を担当する。
|
|
17
|
+
* プロセス再起動でクリアされるため、ローカル開発・SSG ビルド・テスト用途。
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* cache: [memoryCache({ maxItems: 1000 })]
|
|
21
|
+
*/
|
|
22
|
+
declare function memoryCache(options?: MemoryCacheOptions): CacheAdapter;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { MemoryCacheOptions, MemoryDocumentOptions, MemoryImageOptions, memoryCache };
|
|
25
|
+
//# sourceMappingURL=memory.d.mts.map
|
|
@@ -133,26 +133,5 @@ interface CacheAdapter {
|
|
|
133
133
|
img?: ImageCacheOps;
|
|
134
134
|
}
|
|
135
135
|
//#endregion
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/** アイテム保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
139
|
-
maxItems?: number;
|
|
140
|
-
}
|
|
141
|
-
interface MemoryImageOptions {
|
|
142
|
-
/** エントリ保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
143
|
-
maxItems?: number;
|
|
144
|
-
/** 合計保持サイズ上限(バイト)。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
145
|
-
maxSizeBytes?: number;
|
|
146
|
-
}
|
|
147
|
-
interface MemoryCacheOptions extends MemoryDocumentOptions, MemoryImageOptions {}
|
|
148
|
-
/**
|
|
149
|
-
* インメモリのキャッシュアダプタ。document + image 両方を担当する。
|
|
150
|
-
* プロセス再起動でクリアされるため、ローカル開発・SSG ビルド・テスト用途。
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* cache: [memoryCache({ maxItems: 1000 })]
|
|
154
|
-
*/
|
|
155
|
-
declare function memoryCache(options?: MemoryCacheOptions): CacheAdapter;
|
|
156
|
-
//#endregion
|
|
157
|
-
export { CacheAdapter as a, DataSource as c, PropertyDef as d, PropertyMap as f, memoryCache as i, InvalidateKind as l, MemoryDocumentOptions as n, DocumentCacheOps as o, WebhookConfig as p, MemoryImageOptions as r, ImageCacheOps as s, MemoryCacheOptions as t, InvalidateScope as u };
|
|
158
|
-
//# sourceMappingURL=memory-BT9rLPr1.d.mts.map
|
|
136
|
+
export { InvalidateKind as a, PropertyMap as c, DataSource as i, WebhookConfig as l, DocumentCacheOps as n, InvalidateScope as o, ImageCacheOps as r, PropertyDef as s, CacheAdapter as t };
|
|
137
|
+
//# sourceMappingURL=cache-DS81aOcC.d.mts.map
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { t as BaseContentItem } from "./content-DwsfWZao.mjs";
|
|
2
|
+
import { i as DataSource, t as CacheAdapter } from "./cache-DS81aOcC.mjs";
|
|
3
|
+
import { i as CMSHooks, r as Logger, t as CMSPlugin } from "./plugin-B795Ok3X.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/types/sources.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* CMS データソースアダプターのインターフェース。
|
|
8
|
+
* 各アダプターパッケージ (`@notion-headless-cms/notion-source` 等) が実装し、
|
|
9
|
+
* `createClient({ sources: { ... } })` に渡される。
|
|
10
|
+
*/
|
|
11
|
+
interface CMSAdapter<C extends CollectionsConfig = CollectionsConfig> {
|
|
12
|
+
readonly collections: C;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* アダプターパッケージが宣言マージで拡張する空インターフェース。
|
|
16
|
+
* import するだけでキーが補完候補に現れる (Fastify プラグインと同じパターン)。
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* declare module "@notion-headless-cms/core" {
|
|
20
|
+
* interface CMSSources {
|
|
21
|
+
* notion?: CMSAdapter;
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
*/
|
|
25
|
+
interface CMSSources {}
|
|
26
|
+
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
27
|
+
/** 全ソースの collections を交差型でマージする。 */
|
|
28
|
+
type MergeSourceCollections<S extends CMSSources> = UnionToIntersection<{ [K in keyof S]: S[K] extends CMSAdapter<infer C> ? C : never }[keyof S]>;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/types/config.d.ts
|
|
31
|
+
/** `Logger` の出力を絞り込むログレベル。指定したレベル未満のログを抑制する。 */
|
|
32
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
33
|
+
/**
|
|
34
|
+
* renderer プラグインの不透明型。
|
|
35
|
+
* core は unified / remark / rehype に依存せず、このリストをそのまま renderer に渡すだけ。
|
|
36
|
+
*/
|
|
37
|
+
type RendererPluginList = unknown[];
|
|
38
|
+
/**
|
|
39
|
+
* render() オプション。core は renderer の実装を知らず、この型だけを扱う。
|
|
40
|
+
* @notion-headless-cms/markdown-html の renderMarkdown() はこのシグネチャと構造的に互換。
|
|
41
|
+
*/
|
|
42
|
+
interface RenderOptions {
|
|
43
|
+
imageProxyBase?: string;
|
|
44
|
+
cacheImage?: (url: string) => Promise<string>;
|
|
45
|
+
remarkPlugins?: RendererPluginList;
|
|
46
|
+
rehypePlugins?: RendererPluginList;
|
|
47
|
+
}
|
|
48
|
+
/** カスタムレンダラー関数の型。デフォルトは @notion-headless-cms/markdown-html の renderMarkdown。 */
|
|
49
|
+
type RendererFn = (markdown: string, opts?: RenderOptions) => Promise<string>;
|
|
50
|
+
/** レンダリング・コンテンツ処理設定。 */
|
|
51
|
+
interface ContentConfig {
|
|
52
|
+
/** 追加する remark プラグイン。 */
|
|
53
|
+
remarkPlugins?: RendererPluginList;
|
|
54
|
+
/** 追加する rehype プラグイン。 */
|
|
55
|
+
rehypePlugins?: RendererPluginList;
|
|
56
|
+
}
|
|
57
|
+
/** SWR(Stale-While-Revalidate)設定。 */
|
|
58
|
+
interface SWRConfig {
|
|
59
|
+
/** SWR の有効期間 (ミリ秒)。未設定時は TTL なし(失効まで stale を返す)。 */
|
|
60
|
+
ttlMs?: number;
|
|
61
|
+
}
|
|
62
|
+
/** レートリミット・リトライ設定。 */
|
|
63
|
+
interface RateLimiterConfig {
|
|
64
|
+
/** 同時実行数の上限。デフォルト: 3 */
|
|
65
|
+
maxConcurrent?: number;
|
|
66
|
+
/** リトライ対象の HTTP ステータスコード。デフォルト: [429, 502, 503] */
|
|
67
|
+
retryOn?: number[];
|
|
68
|
+
/** 最大リトライ回数。デフォルト: 4 */
|
|
69
|
+
maxRetries?: number;
|
|
70
|
+
/** リトライ時の基準待機時間(ミリ秒)。デフォルト: 1000 */
|
|
71
|
+
baseDelayMs?: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* コレクション 1 件の定義。CLI が生成する `nhc.ts` から `createClient` に渡される。
|
|
75
|
+
*
|
|
76
|
+
* `source` は notion-orm 等の DataSource 実装。
|
|
77
|
+
* `slugField` / `statusField` は TS フィールド名 (DataSource の `properties` キーと一致)。
|
|
78
|
+
*/
|
|
79
|
+
interface CollectionDef<T extends BaseContentItem = BaseContentItem> {
|
|
80
|
+
/** Notion etc. のデータソース実装。 */
|
|
81
|
+
source: DataSource<T>;
|
|
82
|
+
/** slug として使う TS フィールド名 (必須)。`source.properties[slugField]` で Notion プロパティ名を解決する。 */
|
|
83
|
+
slugField: string;
|
|
84
|
+
/** ステータスとして使う TS フィールド名。 */
|
|
85
|
+
statusField?: string;
|
|
86
|
+
/** 公開扱いするステータス値。`list()` のデフォルト絞り込みに使う。 */
|
|
87
|
+
publishedStatuses?: readonly string[];
|
|
88
|
+
/** アクセス許可するステータス値。`get()` の閲覧可否判定に使う。 */
|
|
89
|
+
accessibleStatuses?: readonly string[];
|
|
90
|
+
/** コレクション固有のライフサイクルフック。グローバル hooks の後に実行される。 */
|
|
91
|
+
hooks?: CMSHooks<T>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* `createClient({ collections })` の map 型。
|
|
95
|
+
* キーがコレクション名、値が `CollectionDef<T>`。
|
|
96
|
+
*/
|
|
97
|
+
type CollectionsConfig = Record<string, CollectionDef<BaseContentItem>>;
|
|
98
|
+
/** `CollectionsConfig` から各 T を抽出するユーティリティ型。 */
|
|
99
|
+
type InferCollectionItem<C> = C extends CollectionDef<infer T> ? T : BaseContentItem;
|
|
100
|
+
/**
|
|
101
|
+
* `createClient()` の入力。
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* import { createClient, nodePreset } from "@notion-headless-cms/core";
|
|
105
|
+
* import { notionSource } from "@notion-headless-cms/notion-source";
|
|
106
|
+
* import { schema } from "./generated/nhc.schema";
|
|
107
|
+
*
|
|
108
|
+
* const cms = createClient({
|
|
109
|
+
* sources: { notion: notionSource({ schema, token: process.env.NOTION_TOKEN! }) },
|
|
110
|
+
* ...nodePreset(),
|
|
111
|
+
* });
|
|
112
|
+
*/
|
|
113
|
+
interface CreateClientOptions<S extends CMSSources = CMSSources> {
|
|
114
|
+
/** データソースアダプター (`@notion-headless-cms/notion-source` 等) のマップ。 */
|
|
115
|
+
sources?: S;
|
|
116
|
+
/**
|
|
117
|
+
* キャッシュアダプタ (配列)。未指定時はキャッシュなし。
|
|
118
|
+
* - `memoryCache()` のように doc + image 両方を担当するもの
|
|
119
|
+
* - `r2Cache()` (image のみ)、`kvCache()` (doc のみ) のように片側のみ担当するもの
|
|
120
|
+
* - 複数 adapter を配列で組み合わせると、各 adapter の `handles` で振り分けられる
|
|
121
|
+
*/
|
|
122
|
+
cache?: readonly CacheAdapter[];
|
|
123
|
+
/** SWR(Stale-While-Revalidate)設定。 */
|
|
124
|
+
swr?: SWRConfig;
|
|
125
|
+
/**
|
|
126
|
+
* Markdown→HTML レンダラー。
|
|
127
|
+
* 省略時は `@notion-headless-cms/markdown-html` の `renderMarkdown` を動的 import で使用する。
|
|
128
|
+
* カスタム実装も `RendererFn` 型を満たせば使用可能。
|
|
129
|
+
*/
|
|
130
|
+
renderer?: RendererFn;
|
|
131
|
+
/** 画像プロキシのベース URL。デフォルト `/api/images`。 */
|
|
132
|
+
imageProxyBase?: string;
|
|
133
|
+
/** Cloudflare Workers の `waitUntil` に相当する非同期処理の登録関数。 */
|
|
134
|
+
waitUntil?: (p: Promise<unknown>) => void;
|
|
135
|
+
/** ライフサイクルフック (全コレクション共通)。 */
|
|
136
|
+
hooks?: CMSHooks<BaseContentItem>;
|
|
137
|
+
/** プラグイン配列。 */
|
|
138
|
+
plugins?: CMSPlugin<BaseContentItem>[];
|
|
139
|
+
/** ロガー。 */
|
|
140
|
+
logger?: Logger;
|
|
141
|
+
/** ログレベルの下限。指定したレベル未満のログを内部で抑制する。 */
|
|
142
|
+
logLevel?: LogLevel;
|
|
143
|
+
/** レートリミット・リトライ設定。 */
|
|
144
|
+
rateLimiter?: RateLimiterConfig;
|
|
145
|
+
/** レンダリング・コンテンツ処理設定。 */
|
|
146
|
+
content?: ContentConfig;
|
|
147
|
+
}
|
|
148
|
+
//#endregion
|
|
149
|
+
export { InferCollectionItem as a, RenderOptions as c, SWRConfig as d, CMSAdapter as f, CreateClientOptions as i, RendererFn as l, MergeSourceCollections as m, CollectionsConfig as n, LogLevel as o, CMSSources as p, ContentConfig as r, RateLimiterConfig as s, CollectionDef as t, RendererPluginList as u };
|
|
150
|
+
//# sourceMappingURL=config-D4JQ_pmq.d.mts.map
|
|
@@ -51,16 +51,27 @@ declare class CMSError extends Error {
|
|
|
51
51
|
readonly code: CMSErrorCode;
|
|
52
52
|
readonly cause?: unknown;
|
|
53
53
|
readonly context: CMSErrorContext;
|
|
54
|
+
/** エラーを解消するための次のアクション(表示用)。 */
|
|
55
|
+
readonly nextSteps?: readonly string[];
|
|
56
|
+
/** 詳細ドキュメントへの URL(表示用)。 */
|
|
57
|
+
readonly docsUrl?: string;
|
|
54
58
|
constructor(params: {
|
|
55
59
|
code: CMSErrorCode;
|
|
56
60
|
message: string;
|
|
57
61
|
cause?: unknown;
|
|
58
62
|
context: CMSErrorContext;
|
|
63
|
+
nextSteps?: readonly string[];
|
|
64
|
+
docsUrl?: string;
|
|
59
65
|
});
|
|
60
66
|
/** エラーコードが指定した値と一致するか判定する。 */
|
|
61
67
|
is(code: CMSErrorCode): boolean;
|
|
62
68
|
/** エラーコードが指定した名前空間に属するか判定する(例: `"source/"`)。 */
|
|
63
69
|
inNamespace(namespace: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* nextSteps と docsUrl を含む人間向けの詳細メッセージを返す。
|
|
72
|
+
* エラーダイアログ・ログ出力時に使う。
|
|
73
|
+
*/
|
|
74
|
+
format(): string;
|
|
64
75
|
}
|
|
65
76
|
declare function isCMSError(error: unknown): error is CMSError;
|
|
66
77
|
/** エラーコードが特定の名前空間に属するかを判定する(例: "source/")。 */
|
|
@@ -81,4 +92,4 @@ declare function matchCMSError<R>(error: unknown, handlers: Partial<Record<CMSEr
|
|
|
81
92
|
}): R | undefined;
|
|
82
93
|
//#endregion
|
|
83
94
|
export { isCMSError as a, CMSErrorContext as i, CMSError as n, isCMSErrorInNamespace as o, CMSErrorCode as r, matchCMSError as s, BuiltInCMSErrorCode as t };
|
|
84
|
-
//# sourceMappingURL=errors-
|
|
95
|
+
//# sourceMappingURL=errors-DTt9ii0i.d.mts.map
|
package/dist/errors.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as isCMSError, i as CMSErrorContext, n as CMSError, o as isCMSErrorInNamespace, r as CMSErrorCode, s as matchCMSError, t as BuiltInCMSErrorCode } from "./errors-
|
|
1
|
+
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";
|
|
2
2
|
export { BuiltInCMSErrorCode, CMSError, CMSErrorCode, CMSErrorContext, isCMSError, isCMSErrorInNamespace, matchCMSError };
|
package/dist/errors.mjs
CHANGED
|
@@ -3,12 +3,18 @@ var CMSError = class extends Error {
|
|
|
3
3
|
code;
|
|
4
4
|
cause;
|
|
5
5
|
context;
|
|
6
|
+
/** エラーを解消するための次のアクション(表示用)。 */
|
|
7
|
+
nextSteps;
|
|
8
|
+
/** 詳細ドキュメントへの URL(表示用)。 */
|
|
9
|
+
docsUrl;
|
|
6
10
|
constructor(params) {
|
|
7
11
|
super(params.message, { cause: params.cause });
|
|
8
12
|
this.name = "CMSError";
|
|
9
13
|
this.code = params.code;
|
|
10
14
|
this.cause = params.cause;
|
|
11
15
|
this.context = params.context;
|
|
16
|
+
this.nextSteps = params.nextSteps;
|
|
17
|
+
this.docsUrl = params.docsUrl;
|
|
12
18
|
}
|
|
13
19
|
/** エラーコードが指定した値と一致するか判定する。 */
|
|
14
20
|
is(code) {
|
|
@@ -18,6 +24,19 @@ var CMSError = class extends Error {
|
|
|
18
24
|
inNamespace(namespace) {
|
|
19
25
|
return this.code.startsWith(namespace);
|
|
20
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* nextSteps と docsUrl を含む人間向けの詳細メッセージを返す。
|
|
29
|
+
* エラーダイアログ・ログ出力時に使う。
|
|
30
|
+
*/
|
|
31
|
+
format() {
|
|
32
|
+
const lines = [this.message];
|
|
33
|
+
if (this.nextSteps?.length) {
|
|
34
|
+
lines.push("\n次にやること:");
|
|
35
|
+
for (const step of this.nextSteps) lines.push(` - ${step}`);
|
|
36
|
+
}
|
|
37
|
+
if (this.docsUrl) lines.push(`\n詳細: ${this.docsUrl}`);
|
|
38
|
+
return lines.join("\n");
|
|
39
|
+
}
|
|
21
40
|
};
|
|
22
41
|
function isCMSError(error) {
|
|
23
42
|
return error instanceof CMSError;
|
package/dist/errors.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * ライブラリ組み込みの CMS エラーコード。\n *\n * | コード | 発生条件 |\n * |---|---|\n * | `core/config_invalid` | 設定不備(token 未設定など) |\n * | `core/schema_invalid` | schema/mapping の型不整合 |\n * | `core/notion_orm_missing` | `@notion-headless-cms/notion-orm` の動的ロード失敗 |\n * | `core/sort_unsupported_type` | ソートキーの値型が string / number でない |\n * | `webhook/signature_invalid` | Webhook 署名検証失敗 |\n * | `webhook/payload_invalid` | Webhook ペイロード形式不正 |\n * | `webhook/unknown_collection` | Webhook の対象コレクションが未知 |\n * | `webhook/not_implemented` | DataSource が parseWebhook を実装していない |\n * | `source/fetch_items_failed` | `DataSource.list()` 失敗 |\n * | `source/fetch_item_failed` | `DataSource.findByProp()` 失敗 |\n * | `source/load_markdown_failed` | `DataSource.loadMarkdown()` 失敗 |\n * | `source/load_blocks_failed` | `DataSource.loadBlocks()` 失敗 |\n * | `cache/io_failed` | document / image キャッシュの I/O 失敗 |\n * | `cache/image_fetch_failed` | Notion 画像の HTTP 取得失敗 |\n * | `cache/image_invalid_content_type` | 画像レスポンスの Content-Type が不正 |\n * | `renderer/failed` | Markdown → HTML 変換失敗 |\n * | `swr/item_check_failed` | SWR バックグラウンドのアイテム差分チェック失敗 |\n * | `swr/list_check_failed` | SWR バックグラウンドのリスト差分チェック失敗 |\n * | `swr/content_rebuild_failed` | SWR バックグラウンドの本文再生成失敗 |\n * | `cli/config_invalid` | `nhc.config.ts` の内容不整合 |\n * | `cli/config_load_failed` | 設定ファイルの読み込み / 評価失敗 |\n * | `cli/schema_invalid` | CLI が受け取ったスキーマ / マッピング不整合 |\n * | `cli/generate_failed` | `nhc generate` の処理失敗 |\n * | `cli/init_failed` | `nhc init` の処理失敗 |\n * | `cli/notion_api_failed` | CLI が Notion API を呼び出す際の失敗 |\n * | `cli/env_file_not_found` | `--env-file` で指定したファイルが存在しない |\n *\n * サードパーティアダプタが独自コードを追加したい場合は `CMSErrorCode` を参照。\n */\nexport type BuiltInCMSErrorCode =\n | \"core/config_invalid\"\n | \"core/schema_invalid\"\n | \"core/notion_orm_missing\"\n | \"core/sort_unsupported_type\"\n | \"webhook/signature_invalid\"\n | \"webhook/payload_invalid\"\n | \"webhook/unknown_collection\"\n | \"webhook/not_implemented\"\n | \"source/fetch_items_failed\"\n | \"source/fetch_item_failed\"\n | \"source/load_markdown_failed\"\n | \"source/load_blocks_failed\"\n | \"cache/io_failed\"\n | \"cache/image_fetch_failed\"\n | \"cache/image_invalid_content_type\"\n | \"renderer/failed\"\n | \"swr/item_check_failed\"\n | \"swr/list_check_failed\"\n | \"swr/content_rebuild_failed\"\n | \"cli/config_invalid\"\n | \"cli/config_load_failed\"\n | \"cli/schema_invalid\"\n | \"cli/generate_failed\"\n | \"cli/init_failed\"\n | \"cli/notion_api_failed\"\n | \"cli/env_file_not_found\";\n\n/**\n * CMS エラーコード。\n * `BuiltInCMSErrorCode` のリテラル補完を維持しつつ、\n * サードパーティアダプタが独自コードを定義できるよう `string & {}` で拡張可能にする。\n */\nexport type CMSErrorCode = BuiltInCMSErrorCode | (string & {});\n\nexport interface CMSErrorContext {\n operation: string;\n slug?: string;\n dataSourceId?: string;\n pageId?: string;\n [key: string]: string | number | boolean | null | undefined;\n}\n\nexport class CMSError extends Error {\n readonly code: CMSErrorCode;\n override readonly cause?: unknown;\n readonly context: CMSErrorContext;\n\n constructor(params: {\n code: CMSErrorCode;\n message: string;\n cause?: unknown;\n context: CMSErrorContext;\n }) {\n super(params.message, { cause: params.cause });\n this.name = \"CMSError\";\n this.code = params.code;\n this.cause = params.cause;\n this.context = params.context;\n }\n\n /** エラーコードが指定した値と一致するか判定する。 */\n is(code: CMSErrorCode): boolean {\n return this.code === code;\n }\n\n /** エラーコードが指定した名前空間に属するか判定する(例: `\"source/\"`)。 */\n inNamespace(namespace: string): boolean {\n return this.code.startsWith(namespace);\n }\n}\n\nexport function isCMSError(error: unknown): error is CMSError {\n return error instanceof CMSError;\n}\n\n/** エラーコードが特定の名前空間に属するかを判定する(例: \"source/\")。 */\nexport function isCMSErrorInNamespace(\n error: unknown,\n namespace: string,\n): error is CMSError {\n return isCMSError(error) && error.code.startsWith(namespace);\n}\n\ntype CMSErrorHandler<R> = (err: CMSError) => R;\n\n/**\n * `CMSError` を switch 式のように分岐して処理するユーティリティ。\n * `_` キーはフォールバック(CMSError 以外 or 未マッチ時)に使われる。\n *\n * @example\n * matchCMSError(err, {\n * \"source/fetch_items_failed\": (e) => handleFetchError(e),\n * _: (e) => { throw e; },\n * });\n */\nexport function matchCMSError<R>(\n error: unknown,\n handlers: Partial<Record<CMSErrorCode, CMSErrorHandler<R>>> & {\n _?: (err: unknown) => R;\n },\n): R | undefined {\n if (!isCMSError(error)) {\n return handlers._?.(error);\n }\n const handler =\n handlers[error.code as CMSErrorCode] ??\n (handlers._ as CMSErrorHandler<R> | undefined);\n return handler?.(error);\n}\n"],"mappings":";AA6EA,IAAa,WAAb,cAA8B,MAAM;CAClC;CACA;CACA;CAEA,YAAY,
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * ライブラリ組み込みの CMS エラーコード。\n *\n * | コード | 発生条件 |\n * |---|---|\n * | `core/config_invalid` | 設定不備(token 未設定など) |\n * | `core/schema_invalid` | schema/mapping の型不整合 |\n * | `core/notion_orm_missing` | `@notion-headless-cms/notion-orm` の動的ロード失敗 |\n * | `core/sort_unsupported_type` | ソートキーの値型が string / number でない |\n * | `webhook/signature_invalid` | Webhook 署名検証失敗 |\n * | `webhook/payload_invalid` | Webhook ペイロード形式不正 |\n * | `webhook/unknown_collection` | Webhook の対象コレクションが未知 |\n * | `webhook/not_implemented` | DataSource が parseWebhook を実装していない |\n * | `source/fetch_items_failed` | `DataSource.list()` 失敗 |\n * | `source/fetch_item_failed` | `DataSource.findByProp()` 失敗 |\n * | `source/load_markdown_failed` | `DataSource.loadMarkdown()` 失敗 |\n * | `source/load_blocks_failed` | `DataSource.loadBlocks()` 失敗 |\n * | `cache/io_failed` | document / image キャッシュの I/O 失敗 |\n * | `cache/image_fetch_failed` | Notion 画像の HTTP 取得失敗 |\n * | `cache/image_invalid_content_type` | 画像レスポンスの Content-Type が不正 |\n * | `renderer/failed` | Markdown → HTML 変換失敗 |\n * | `swr/item_check_failed` | SWR バックグラウンドのアイテム差分チェック失敗 |\n * | `swr/list_check_failed` | SWR バックグラウンドのリスト差分チェック失敗 |\n * | `swr/content_rebuild_failed` | SWR バックグラウンドの本文再生成失敗 |\n * | `cli/config_invalid` | `nhc.config.ts` の内容不整合 |\n * | `cli/config_load_failed` | 設定ファイルの読み込み / 評価失敗 |\n * | `cli/schema_invalid` | CLI が受け取ったスキーマ / マッピング不整合 |\n * | `cli/generate_failed` | `nhc generate` の処理失敗 |\n * | `cli/init_failed` | `nhc init` の処理失敗 |\n * | `cli/notion_api_failed` | CLI が Notion API を呼び出す際の失敗 |\n * | `cli/env_file_not_found` | `--env-file` で指定したファイルが存在しない |\n *\n * サードパーティアダプタが独自コードを追加したい場合は `CMSErrorCode` を参照。\n */\nexport type BuiltInCMSErrorCode =\n | \"core/config_invalid\"\n | \"core/schema_invalid\"\n | \"core/notion_orm_missing\"\n | \"core/sort_unsupported_type\"\n | \"webhook/signature_invalid\"\n | \"webhook/payload_invalid\"\n | \"webhook/unknown_collection\"\n | \"webhook/not_implemented\"\n | \"source/fetch_items_failed\"\n | \"source/fetch_item_failed\"\n | \"source/load_markdown_failed\"\n | \"source/load_blocks_failed\"\n | \"cache/io_failed\"\n | \"cache/image_fetch_failed\"\n | \"cache/image_invalid_content_type\"\n | \"renderer/failed\"\n | \"swr/item_check_failed\"\n | \"swr/list_check_failed\"\n | \"swr/content_rebuild_failed\"\n | \"cli/config_invalid\"\n | \"cli/config_load_failed\"\n | \"cli/schema_invalid\"\n | \"cli/generate_failed\"\n | \"cli/init_failed\"\n | \"cli/notion_api_failed\"\n | \"cli/env_file_not_found\";\n\n/**\n * CMS エラーコード。\n * `BuiltInCMSErrorCode` のリテラル補完を維持しつつ、\n * サードパーティアダプタが独自コードを定義できるよう `string & {}` で拡張可能にする。\n */\nexport type CMSErrorCode = BuiltInCMSErrorCode | (string & {});\n\nexport interface CMSErrorContext {\n operation: string;\n slug?: string;\n dataSourceId?: string;\n pageId?: string;\n [key: string]: string | number | boolean | null | undefined;\n}\n\nexport class CMSError extends Error {\n readonly code: CMSErrorCode;\n override readonly cause?: unknown;\n readonly context: CMSErrorContext;\n /** エラーを解消するための次のアクション(表示用)。 */\n readonly nextSteps?: readonly string[];\n /** 詳細ドキュメントへの URL(表示用)。 */\n readonly docsUrl?: string;\n\n constructor(params: {\n code: CMSErrorCode;\n message: string;\n cause?: unknown;\n context: CMSErrorContext;\n nextSteps?: readonly string[];\n docsUrl?: string;\n }) {\n super(params.message, { cause: params.cause });\n this.name = \"CMSError\";\n this.code = params.code;\n this.cause = params.cause;\n this.context = params.context;\n this.nextSteps = params.nextSteps;\n this.docsUrl = params.docsUrl;\n }\n\n /** エラーコードが指定した値と一致するか判定する。 */\n is(code: CMSErrorCode): boolean {\n return this.code === code;\n }\n\n /** エラーコードが指定した名前空間に属するか判定する(例: `\"source/\"`)。 */\n inNamespace(namespace: string): boolean {\n return this.code.startsWith(namespace);\n }\n\n /**\n * nextSteps と docsUrl を含む人間向けの詳細メッセージを返す。\n * エラーダイアログ・ログ出力時に使う。\n */\n format(): string {\n const lines: string[] = [this.message];\n if (this.nextSteps?.length) {\n lines.push(\"\\n次にやること:\");\n for (const step of this.nextSteps) {\n lines.push(` - ${step}`);\n }\n }\n if (this.docsUrl) {\n lines.push(`\\n詳細: ${this.docsUrl}`);\n }\n return lines.join(\"\\n\");\n }\n}\n\nexport function isCMSError(error: unknown): error is CMSError {\n return error instanceof CMSError;\n}\n\n/** エラーコードが特定の名前空間に属するかを判定する(例: \"source/\")。 */\nexport function isCMSErrorInNamespace(\n error: unknown,\n namespace: string,\n): error is CMSError {\n return isCMSError(error) && error.code.startsWith(namespace);\n}\n\ntype CMSErrorHandler<R> = (err: CMSError) => R;\n\n/**\n * `CMSError` を switch 式のように分岐して処理するユーティリティ。\n * `_` キーはフォールバック(CMSError 以外 or 未マッチ時)に使われる。\n *\n * @example\n * matchCMSError(err, {\n * \"source/fetch_items_failed\": (e) => handleFetchError(e),\n * _: (e) => { throw e; },\n * });\n */\nexport function matchCMSError<R>(\n error: unknown,\n handlers: Partial<Record<CMSErrorCode, CMSErrorHandler<R>>> & {\n _?: (err: unknown) => R;\n },\n): R | undefined {\n if (!isCMSError(error)) {\n return handlers._?.(error);\n }\n const handler =\n handlers[error.code as CMSErrorCode] ??\n (handlers._ as CMSErrorHandler<R> | undefined);\n return handler?.(error);\n}\n"],"mappings":";AA6EA,IAAa,WAAb,cAA8B,MAAM;CAClC;CACA;CACA;;CAEA;;CAEA;CAEA,YAAY,QAOT;AACD,QAAM,OAAO,SAAS,EAAE,OAAO,OAAO,OAAO,CAAC;AAC9C,OAAK,OAAO;AACZ,OAAK,OAAO,OAAO;AACnB,OAAK,QAAQ,OAAO;AACpB,OAAK,UAAU,OAAO;AACtB,OAAK,YAAY,OAAO;AACxB,OAAK,UAAU,OAAO;;;CAIxB,GAAG,MAA6B;AAC9B,SAAO,KAAK,SAAS;;;CAIvB,YAAY,WAA4B;AACtC,SAAO,KAAK,KAAK,WAAW,UAAU;;;;;;CAOxC,SAAiB;EACf,MAAM,QAAkB,CAAC,KAAK,QAAQ;AACtC,MAAI,KAAK,WAAW,QAAQ;AAC1B,SAAM,KAAK,YAAY;AACvB,QAAK,MAAM,QAAQ,KAAK,UACtB,OAAM,KAAK,OAAO,OAAO;;AAG7B,MAAI,KAAK,QACP,OAAM,KAAK,SAAS,KAAK,UAAU;AAErC,SAAO,MAAM,KAAK,KAAK;;;AAI3B,SAAgB,WAAW,OAAmC;AAC5D,QAAO,iBAAiB;;;AAI1B,SAAgB,sBACd,OACA,WACmB;AACnB,QAAO,WAAW,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU;;;;;;;;;;;;AAe9D,SAAgB,cACd,OACA,UAGe;AACf,KAAI,CAAC,WAAW,MAAM,CACpB,QAAO,SAAS,IAAI,MAAM;AAK5B,SAFE,SAAS,MAAM,SACd,SAAS,KACK,MAAM"}
|
package/dist/hooks.d.mts
CHANGED
|
@@ -1,2 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { t as BaseContentItem } from "./content-DwsfWZao.mjs";
|
|
2
|
+
import { i as CMSHooks, r as Logger, t as CMSPlugin } from "./plugin-B795Ok3X.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/hooks.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。
|
|
7
|
+
* beforeCacheMeta / beforeCacheContent / afterRender はパイプライン(前の出力が次の入力)。
|
|
8
|
+
* オブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。
|
|
9
|
+
*/
|
|
10
|
+
declare function mergeHooks<T extends BaseContentItem>(plugins: CMSPlugin<T>[], directHooks?: CMSHooks<T>, logger?: Logger): CMSHooks<T>;
|
|
11
|
+
/** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */
|
|
12
|
+
declare function mergeLoggers(plugins: Array<{
|
|
13
|
+
logger?: Partial<Logger>;
|
|
14
|
+
}>, directLogger?: Logger): Logger | undefined;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { mergeHooks, mergeLoggers };
|
|
17
|
+
//# sourceMappingURL=hooks.d.mts.map
|
package/dist/html.d.mts
CHANGED
|
@@ -2,20 +2,26 @@
|
|
|
2
2
|
interface NotionRevalidatorScriptOptions {
|
|
3
3
|
/**
|
|
4
4
|
* 再検証のトリガー。既定値: "visibility"
|
|
5
|
-
* - "visibility":
|
|
5
|
+
* - "visibility": `visibilitychange` で hidden→visible の度に reload
|
|
6
6
|
* - "focus": ウィンドウ focus の度に reload (visibility より発火が頻繁)
|
|
7
7
|
*/
|
|
8
8
|
on?: "visibility" | "focus";
|
|
9
|
-
/**
|
|
10
|
-
* `<script nonce="...">` を出力したい場合 (CSP 対応)。
|
|
11
|
-
* 英数字・`-` / `_` / `+` / `/` / `=` のみ許可。属性値ブレイクアウトを防ぐため
|
|
12
|
-
* 不正な文字が含まれていれば throw する。
|
|
13
|
-
*/
|
|
9
|
+
/** CSP 対応の `nonce` 値。base64 / base64url 由来の文字のみ許可、不正値は throw する。 */
|
|
14
10
|
nonce?: string;
|
|
15
11
|
}
|
|
16
12
|
/**
|
|
17
|
-
* React
|
|
18
|
-
*
|
|
13
|
+
* React を使わないテンプレート (Astro / Hono / Express など) 向けに、
|
|
14
|
+
* SWR 再検証用の `<script>...</script>` 文字列を返す。
|
|
15
|
+
*
|
|
16
|
+
* タブ可視化や focus を検知して `location.reload()` を呼び、サーバ側で
|
|
17
|
+
* `waitUntil` 配線済みの SWR bg が更新したキャッシュを次回訪問時に取得する。
|
|
18
|
+
* クエリ無し・別 API fetch 無し。
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Astro
|
|
22
|
+
* <Fragment set:html={notionRevalidatorScript()} />
|
|
23
|
+
* // Hono
|
|
24
|
+
* c.html(h`...${raw(notionRevalidatorScript())}`);
|
|
19
25
|
*/
|
|
20
26
|
declare function notionRevalidatorScript(opts?: NotionRevalidatorScriptOptions): string;
|
|
21
27
|
//#endregion
|
package/dist/html.mjs
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
//#region src/html.ts
|
|
2
2
|
const NONCE_PATTERN = /^[A-Za-z0-9+/=_-]+$/;
|
|
3
3
|
/**
|
|
4
|
-
* React
|
|
5
|
-
*
|
|
4
|
+
* React を使わないテンプレート (Astro / Hono / Express など) 向けに、
|
|
5
|
+
* SWR 再検証用の `<script>...<\/script>` 文字列を返す。
|
|
6
|
+
*
|
|
7
|
+
* タブ可視化や focus を検知して `location.reload()` を呼び、サーバ側で
|
|
8
|
+
* `waitUntil` 配線済みの SWR bg が更新したキャッシュを次回訪問時に取得する。
|
|
9
|
+
* クエリ無し・別 API fetch 無し。
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Astro
|
|
13
|
+
* <Fragment set:html={notionRevalidatorScript()} />
|
|
14
|
+
* // Hono
|
|
15
|
+
* c.html(h`...${raw(notionRevalidatorScript())}`);
|
|
6
16
|
*/
|
|
7
17
|
function notionRevalidatorScript(opts = {}) {
|
|
8
18
|
const body = (opts.on ?? "visibility") === "focus" ? "let l=false;addEventListener(\"focus\",()=>{if(l)location.reload();l=true});" : "document.addEventListener(\"visibilitychange\",()=>{if(document.visibilityState===\"visible\")location.reload()});";
|
package/dist/html.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.mjs","names":[],"sources":["../src/html.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"html.mjs","names":[],"sources":["../src/html.ts"],"sourcesContent":["export interface NotionRevalidatorScriptOptions {\n /**\n * 再検証のトリガー。既定値: \"visibility\"\n * - \"visibility\": `visibilitychange` で hidden→visible の度に reload\n * - \"focus\": ウィンドウ focus の度に reload (visibility より発火が頻繁)\n */\n on?: \"visibility\" | \"focus\";\n /** CSP 対応の `nonce` 値。base64 / base64url 由来の文字のみ許可、不正値は throw する。 */\n nonce?: string;\n}\n\n// 属性値ブレイクアウトを防ぐため、CSP nonce は base64 / base64url 範囲に限定して検証する\nconst NONCE_PATTERN = /^[A-Za-z0-9+/=_-]+$/;\n\n/**\n * React を使わないテンプレート (Astro / Hono / Express など) 向けに、\n * SWR 再検証用の `<script>...</script>` 文字列を返す。\n *\n * タブ可視化や focus を検知して `location.reload()` を呼び、サーバ側で\n * `waitUntil` 配線済みの SWR bg が更新したキャッシュを次回訪問時に取得する。\n * クエリ無し・別 API fetch 無し。\n *\n * @example\n * // Astro\n * <Fragment set:html={notionRevalidatorScript()} />\n * // Hono\n * c.html(h`...${raw(notionRevalidatorScript())}`);\n */\nexport function notionRevalidatorScript(\n opts: NotionRevalidatorScriptOptions = {},\n): string {\n const trigger = opts.on ?? \"visibility\";\n const body =\n trigger === \"focus\"\n ? // 初回ロード直後の focus は無視するため、loaded フラグで初回をスキップ\n 'let l=false;addEventListener(\"focus\",()=>{if(l)location.reload();l=true});'\n : 'document.addEventListener(\"visibilitychange\",()=>{if(document.visibilityState===\"visible\")location.reload()});';\n let nonceAttr = \"\";\n if (opts.nonce !== undefined) {\n if (!NONCE_PATTERN.test(opts.nonce)) {\n throw new Error(\n \"notionRevalidatorScript: nonce に不正な文字が含まれています。base64 / base64url 由来の英数字のみ受け付けます。\",\n );\n }\n nonceAttr = ` nonce=\"${opts.nonce}\"`;\n }\n return `<script${nonceAttr}>(()=>{${body}})();</script>`;\n}\n"],"mappings":";AAYA,MAAM,gBAAgB;;;;;;;;;;;;;;;AAgBtB,SAAgB,wBACd,OAAuC,EAAE,EACjC;CAER,MAAM,QADU,KAAK,MAAM,kBAEb,UAER,iFACA;CACN,IAAI,YAAY;AAChB,KAAI,KAAK,UAAU,KAAA,GAAW;AAC5B,MAAI,CAAC,cAAc,KAAK,KAAK,MAAM,CACjC,OAAM,IAAI,MACR,mFACD;AAEH,cAAY,WAAW,KAAK,MAAM;;AAEpC,QAAO,UAAU,UAAU,SAAS,KAAK"}
|