@notion-headless-cms/core 0.3.25 → 0.5.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 +6 -6
- package/dist/cache/memory.d.mts +3 -1
- package/dist/cache/memory.mjs +56 -6
- package/dist/cache/memory.mjs.map +1 -1
- package/dist/{cache-DS81aOcC.d.mts → cache-v9jTMnYd.d.mts} +70 -9
- package/dist/{config-DYxyW3SR.d.mts → config-i99tKRhN.d.mts} +40 -5
- package/dist/errors.mjs +137 -2
- package/dist/errors.mjs.map +1 -1
- package/dist/hooks.d.mts +10 -2
- package/dist/hooks.mjs +28 -1
- package/dist/hooks.mjs.map +1 -1
- package/dist/index.d.mts +44 -5
- package/dist/index.mjs +116 -9
- package/dist/index.mjs.map +1 -1
- package/dist/{plugin-Dct12kp2.d.mts → plugin-BmrOz8T6.d.mts} +10 -2
- package/dist/preset/node.d.mts +2 -2
- package/dist/source-author.d.mts +1 -1
- package/package.json +3 -2
package/dist/hooks.mjs
CHANGED
|
@@ -82,7 +82,34 @@ function mergeLoggers(plugins, directLogger) {
|
|
|
82
82
|
}
|
|
83
83
|
return merged;
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* 既存 Logger をラップし、全ログコンテキストに `traceId` を自動で付与する。
|
|
87
|
+
* 呼び出し側が明示的に traceId を渡した場合はその値を優先する。
|
|
88
|
+
*
|
|
89
|
+
* `createClient` がクライアント単位の trace ID を発行し、ネストした操作
|
|
90
|
+
* (list / find / SWR 再生成 / retry) で同じ ID をログに伝搬するために使う。
|
|
91
|
+
*/
|
|
92
|
+
function withTraceId(logger, traceId) {
|
|
93
|
+
if (!logger) return void 0;
|
|
94
|
+
const wrapped = {};
|
|
95
|
+
for (const level of [
|
|
96
|
+
"debug",
|
|
97
|
+
"info",
|
|
98
|
+
"warn",
|
|
99
|
+
"error"
|
|
100
|
+
]) {
|
|
101
|
+
const fn = logger[level];
|
|
102
|
+
if (!fn) continue;
|
|
103
|
+
wrapped[level] = (message, context) => {
|
|
104
|
+
fn(message, {
|
|
105
|
+
traceId,
|
|
106
|
+
...context ?? {}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return wrapped;
|
|
111
|
+
}
|
|
85
112
|
//#endregion
|
|
86
|
-
export { mergeHooks, mergeLoggers };
|
|
113
|
+
export { mergeHooks, mergeLoggers, withTraceId };
|
|
87
114
|
|
|
88
115
|
//# sourceMappingURL=hooks.mjs.map
|
package/dist/hooks.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.mjs","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import type { BaseContentItem } from \"./types/content\";\nimport type { CMSHooks, MaybePromise } from \"./types/hooks\";\nimport type { Logger } from \"./types/logger\";\nimport type { CMSPlugin } from \"./types/plugin\";\n\n/**\n * プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。\n * beforeCacheMeta / beforeCacheContent / afterRender はパイプライン(前の出力が次の入力)。\n * オブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。\n */\nexport function mergeHooks<T extends BaseContentItem>(\n plugins: CMSPlugin<T>[],\n directHooks?: CMSHooks<T>,\n logger?: Logger,\n): CMSHooks<T> {\n const allHooks: CMSHooks<T>[] = [\n ...plugins.map((p) => p.hooks ?? {}),\n ...(directHooks ? [directHooks] : []),\n ];\n\n if (allHooks.length === 0) return {};\n\n return {\n beforeCacheMeta: buildMetaPipeline(allHooks),\n beforeCacheContent: buildContentPipeline(allHooks),\n afterRender: buildRenderPipeline(allHooks),\n onCacheHit: buildObserver(allHooks, \"onCacheHit\", logger),\n onCacheMiss: buildObserver(allHooks, \"onCacheMiss\", logger),\n onCacheRevalidated: buildObserver(allHooks, \"onCacheRevalidated\", logger),\n onContentRevalidated: buildObserver(\n allHooks,\n \"onContentRevalidated\",\n logger,\n ),\n onListCacheHit: buildObserver(allHooks, \"onListCacheHit\", logger),\n onListCacheMiss: buildObserver(allHooks, \"onListCacheMiss\", logger),\n onListCacheRevalidated: buildObserver(\n allHooks,\n \"onListCacheRevalidated\",\n logger,\n ),\n onError: buildObserver(allHooks, \"onError\", logger),\n onRenderStart: buildObserver(allHooks, \"onRenderStart\", logger),\n onRenderEnd: buildObserver(allHooks, \"onRenderEnd\", logger),\n };\n}\n\nfunction buildMetaPipeline<T extends BaseContentItem>(\n hooks: CMSHooks<T>[],\n): CMSHooks<T>[\"beforeCacheMeta\"] {\n const fns = hooks\n .map((h) => h.beforeCacheMeta)\n .filter(Boolean) as NonNullable<CMSHooks<T>[\"beforeCacheMeta\"]>[];\n if (fns.length === 0) return undefined;\n return async (meta) => {\n let current = meta;\n for (const fn of fns) {\n current = await (fn(current) as MaybePromise<typeof meta>);\n }\n return current;\n };\n}\n\nfunction buildContentPipeline<T extends BaseContentItem>(\n hooks: CMSHooks<T>[],\n): CMSHooks<T>[\"beforeCacheContent\"] {\n const fns = hooks\n .map((h) => h.beforeCacheContent)\n .filter(Boolean) as NonNullable<CMSHooks<T>[\"beforeCacheContent\"]>[];\n if (fns.length === 0) return undefined;\n return async (content, item) => {\n let current = content;\n for (const fn of fns) {\n current = await (fn(current, item) as MaybePromise<typeof content>);\n }\n return current;\n };\n}\n\nfunction buildRenderPipeline<T extends BaseContentItem>(\n hooks: CMSHooks<T>[],\n): CMSHooks<T>[\"afterRender\"] {\n const fns = hooks.map((h) => h.afterRender).filter(Boolean) as NonNullable<\n CMSHooks<T>[\"afterRender\"]\n >[];\n if (fns.length === 0) return undefined;\n return async (html, item) => {\n let current = html;\n for (const fn of fns) {\n current = await (fn(current, item) as MaybePromise<string>);\n }\n return current;\n };\n}\n\nfunction buildObserver<T extends BaseContentItem, K extends keyof CMSHooks<T>>(\n hooks: CMSHooks<T>[],\n key: K,\n logger?: Logger,\n): CMSHooks<T>[K] {\n const fns = hooks.map((h) => h[key]).filter(Boolean);\n if (fns.length === 0) return undefined;\n return ((...args: unknown[]) => {\n for (const fn of fns) {\n try {\n (fn as (...a: unknown[]) => void)(...args);\n } catch (err) {\n logger?.error?.(\"観測フックで例外が発生\", {\n hook: String(key),\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }) as CMSHooks<T>[K];\n}\n\n/** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */\nexport function mergeLoggers(\n plugins: Array<{ logger?: Partial<Logger> }>,\n directLogger?: Logger,\n): Logger | undefined {\n const loggers: Partial<Logger>[] = [\n ...plugins.map((p) => p.logger ?? {}),\n ...(directLogger ? [directLogger] : []),\n ];\n if (loggers.length === 0) return undefined;\n\n const merged: Logger = {};\n for (const level of [\"debug\", \"info\", \"warn\", \"error\"] as const) {\n const fns = loggers.map((l) => l[level]).filter(Boolean) as NonNullable<\n Logger[typeof level]\n >[];\n if (fns.length > 0) {\n merged[level] = (message, context) => {\n for (const fn of fns) fn(message, context);\n };\n }\n }\n return merged;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hooks.mjs","names":[],"sources":["../src/hooks.ts"],"sourcesContent":["import type { BaseContentItem } from \"./types/content\";\nimport type { CMSHooks, MaybePromise } from \"./types/hooks\";\nimport type { Logger } from \"./types/logger\";\nimport type { CMSPlugin } from \"./types/plugin\";\n\n/**\n * プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。\n * beforeCacheMeta / beforeCacheContent / afterRender はパイプライン(前の出力が次の入力)。\n * オブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。\n */\nexport function mergeHooks<T extends BaseContentItem>(\n plugins: CMSPlugin<T>[],\n directHooks?: CMSHooks<T>,\n logger?: Logger,\n): CMSHooks<T> {\n const allHooks: CMSHooks<T>[] = [\n ...plugins.map((p) => p.hooks ?? {}),\n ...(directHooks ? [directHooks] : []),\n ];\n\n if (allHooks.length === 0) return {};\n\n return {\n beforeCacheMeta: buildMetaPipeline(allHooks),\n beforeCacheContent: buildContentPipeline(allHooks),\n afterRender: buildRenderPipeline(allHooks),\n onCacheHit: buildObserver(allHooks, \"onCacheHit\", logger),\n onCacheMiss: buildObserver(allHooks, \"onCacheMiss\", logger),\n onCacheRevalidated: buildObserver(allHooks, \"onCacheRevalidated\", logger),\n onContentRevalidated: buildObserver(\n allHooks,\n \"onContentRevalidated\",\n logger,\n ),\n onListCacheHit: buildObserver(allHooks, \"onListCacheHit\", logger),\n onListCacheMiss: buildObserver(allHooks, \"onListCacheMiss\", logger),\n onListCacheRevalidated: buildObserver(\n allHooks,\n \"onListCacheRevalidated\",\n logger,\n ),\n onError: buildObserver(allHooks, \"onError\", logger),\n onRenderStart: buildObserver(allHooks, \"onRenderStart\", logger),\n onRenderEnd: buildObserver(allHooks, \"onRenderEnd\", logger),\n };\n}\n\nfunction buildMetaPipeline<T extends BaseContentItem>(\n hooks: CMSHooks<T>[],\n): CMSHooks<T>[\"beforeCacheMeta\"] {\n const fns = hooks\n .map((h) => h.beforeCacheMeta)\n .filter(Boolean) as NonNullable<CMSHooks<T>[\"beforeCacheMeta\"]>[];\n if (fns.length === 0) return undefined;\n return async (meta) => {\n let current = meta;\n for (const fn of fns) {\n current = await (fn(current) as MaybePromise<typeof meta>);\n }\n return current;\n };\n}\n\nfunction buildContentPipeline<T extends BaseContentItem>(\n hooks: CMSHooks<T>[],\n): CMSHooks<T>[\"beforeCacheContent\"] {\n const fns = hooks\n .map((h) => h.beforeCacheContent)\n .filter(Boolean) as NonNullable<CMSHooks<T>[\"beforeCacheContent\"]>[];\n if (fns.length === 0) return undefined;\n return async (content, item) => {\n let current = content;\n for (const fn of fns) {\n current = await (fn(current, item) as MaybePromise<typeof content>);\n }\n return current;\n };\n}\n\nfunction buildRenderPipeline<T extends BaseContentItem>(\n hooks: CMSHooks<T>[],\n): CMSHooks<T>[\"afterRender\"] {\n const fns = hooks.map((h) => h.afterRender).filter(Boolean) as NonNullable<\n CMSHooks<T>[\"afterRender\"]\n >[];\n if (fns.length === 0) return undefined;\n return async (html, item) => {\n let current = html;\n for (const fn of fns) {\n current = await (fn(current, item) as MaybePromise<string>);\n }\n return current;\n };\n}\n\nfunction buildObserver<T extends BaseContentItem, K extends keyof CMSHooks<T>>(\n hooks: CMSHooks<T>[],\n key: K,\n logger?: Logger,\n): CMSHooks<T>[K] {\n const fns = hooks.map((h) => h[key]).filter(Boolean);\n if (fns.length === 0) return undefined;\n return ((...args: unknown[]) => {\n for (const fn of fns) {\n try {\n (fn as (...a: unknown[]) => void)(...args);\n } catch (err) {\n logger?.error?.(\"観測フックで例外が発生\", {\n hook: String(key),\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }) as CMSHooks<T>[K];\n}\n\n/** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */\nexport function mergeLoggers(\n plugins: Array<{ logger?: Partial<Logger> }>,\n directLogger?: Logger,\n): Logger | undefined {\n const loggers: Partial<Logger>[] = [\n ...plugins.map((p) => p.logger ?? {}),\n ...(directLogger ? [directLogger] : []),\n ];\n if (loggers.length === 0) return undefined;\n\n const merged: Logger = {};\n for (const level of [\"debug\", \"info\", \"warn\", \"error\"] as const) {\n const fns = loggers.map((l) => l[level]).filter(Boolean) as NonNullable<\n Logger[typeof level]\n >[];\n if (fns.length > 0) {\n merged[level] = (message, context) => {\n for (const fn of fns) fn(message, context);\n };\n }\n }\n return merged;\n}\n\n/**\n * 既存 Logger をラップし、全ログコンテキストに `traceId` を自動で付与する。\n * 呼び出し側が明示的に traceId を渡した場合はその値を優先する。\n *\n * `createClient` がクライアント単位の trace ID を発行し、ネストした操作\n * (list / find / SWR 再生成 / retry) で同じ ID をログに伝搬するために使う。\n */\nexport function withTraceId(\n logger: Logger | undefined,\n traceId: string,\n): Logger | undefined {\n if (!logger) return undefined;\n const wrapped: Logger = {};\n for (const level of [\"debug\", \"info\", \"warn\", \"error\"] as const) {\n const fn = logger[level];\n if (!fn) continue;\n wrapped[level] = (message, context) => {\n fn(message, { traceId, ...(context ?? {}) });\n };\n }\n return wrapped;\n}\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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
|
|
2
|
+
import { a as ImageCacheOps, c as InvalidateScope, d as WebhookConfig, i as DocumentCacheOps, l as PropertyDef, n as CacheAdapterStats, o as DataSource, r as CacheAreaStats, s as InvalidateKind, t as CacheAdapter, u as PropertyMap } from "./cache-v9jTMnYd.mjs";
|
|
3
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-DcNErfYk.mjs";
|
|
4
|
-
import { a as
|
|
5
|
-
import { a as
|
|
4
|
+
import { a as CMSHooks, i as Logger, n as definePlugin, o as MaybePromise, r as LogContext, t as CMSPlugin } from "./plugin-BmrOz8T6.mjs";
|
|
5
|
+
import { _ as MergeSourceCollections, a as DEFAULT_RATE_LIMITER, c as RateLimiterConfig, d as RendererPluginList, f as SWRConfig, g as CMSSources, i as CreateClientOptions, l as RenderOptions, m as defineCollection, n as CollectionsConfig, o as InferCollectionItem, p as StrictCollectionDef, r as ContentConfig, s as LogLevel, u as RendererFn } from "./config-i99tKRhN.mjs";
|
|
6
6
|
import { MemoryCacheOptions, memoryCache } from "./cache/memory.mjs";
|
|
7
7
|
import { mergeHooks, mergeLoggers } from "./hooks.mjs";
|
|
8
8
|
import { NodePresetOptions, nodePreset } from "./preset/node.mjs";
|
|
@@ -204,8 +204,36 @@ declare function createHandler(adapter: HandlerAdapter, opts?: HandlerOptions):
|
|
|
204
204
|
//#region src/cms.d.ts
|
|
205
205
|
/** コレクション別アクセス + グローバル操作の合成型。 */
|
|
206
206
|
type CMSClient<C extends CollectionsConfig> = { [K in keyof C]: CollectionClient<InferCollectionItem<C[K]>> } & CMSGlobalOps;
|
|
207
|
+
/**
|
|
208
|
+
* `cms.stats()` が返す集約済みキャッシュ統計。
|
|
209
|
+
* 各 adapter の `stats()` 戻り値をそのまま配列で保持しつつ、ヒット率を算出する。
|
|
210
|
+
*/
|
|
211
|
+
interface CMSStats {
|
|
212
|
+
/** クライアント単位の trace ID (`createClient` で発行)。 */
|
|
213
|
+
traceId: string;
|
|
214
|
+
/** ドキュメントキャッシュの集計 (`handles: ["document"]` の adapter の `stats()` 戻り値)。 */
|
|
215
|
+
document?: {
|
|
216
|
+
adapter: string;
|
|
217
|
+
hits: number;
|
|
218
|
+
misses: number;
|
|
219
|
+
entries?: number;
|
|
220
|
+
sizeBytes?: number; /** 0〜1。`hits + misses === 0` のときは 0。 */
|
|
221
|
+
hitRate: number;
|
|
222
|
+
};
|
|
223
|
+
/** 画像キャッシュの集計 (`handles: ["image"]` の adapter の `stats()` 戻り値)。 */
|
|
224
|
+
image?: {
|
|
225
|
+
adapter: string;
|
|
226
|
+
hits: number;
|
|
227
|
+
misses: number;
|
|
228
|
+
entries?: number;
|
|
229
|
+
sizeBytes?: number;
|
|
230
|
+
hitRate: number;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
207
233
|
interface CMSGlobalOps {
|
|
208
234
|
readonly collections: readonly string[];
|
|
235
|
+
/** クライアント単位の trace ID (`createClient` で発行)。 */
|
|
236
|
+
readonly traceId: string;
|
|
209
237
|
invalidate(scope?: InvalidateScope): Promise<void>;
|
|
210
238
|
/** Web Standard な Request/Response ベースのルートハンドラ (画像プロキシ + webhook)。 */
|
|
211
239
|
handler(opts?: HandlerOptions): (req: Request) => Promise<Response>;
|
|
@@ -216,6 +244,12 @@ interface CMSGlobalOps {
|
|
|
216
244
|
*/
|
|
217
245
|
readonly cacheImage: ((url: string) => Promise<string>) | undefined;
|
|
218
246
|
readonly imageProxyBase: string;
|
|
247
|
+
/**
|
|
248
|
+
* ドキュメント / 画像キャッシュのヒット・ミス・サイズを集約して返す。
|
|
249
|
+
* 各キャッシュアダプタの `stats()` を呼ぶだけで副作用はない。
|
|
250
|
+
* `stats()` を実装していない adapter は集計から除外される (noop など)。
|
|
251
|
+
*/
|
|
252
|
+
stats(): Promise<CMSStats>;
|
|
219
253
|
}
|
|
220
254
|
/**
|
|
221
255
|
* CMS クライアントを生成する。
|
|
@@ -241,7 +275,12 @@ interface RetryConfig {
|
|
|
241
275
|
baseDelayMs: number;
|
|
242
276
|
/** true のとき指数バックオフにランダムジッターを加える(Thundering Herd 対策)。デフォルト: true */
|
|
243
277
|
jitter?: boolean;
|
|
244
|
-
|
|
278
|
+
/**
|
|
279
|
+
* リトライ前に呼ばれるフック。`attempt` は 1 始まり、`status` はリトライ対象の HTTP ステータス、
|
|
280
|
+
* `delayMs` は次回試行までの実際の待機時間 (ジッター反映後)。
|
|
281
|
+
* 既存呼び出しは `attempt` / `status` だけで動くよう `delayMs` は省略可。
|
|
282
|
+
*/
|
|
283
|
+
onRetry?: (attempt: number, status: number, delayMs?: number) => void;
|
|
245
284
|
}
|
|
246
285
|
declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
247
286
|
/**
|
|
@@ -254,5 +293,5 @@ declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
|
254
293
|
*/
|
|
255
294
|
declare function withRetry<T>(fn: () => Promise<T>, config: RetryConfig): Promise<T>;
|
|
256
295
|
//#endregion
|
|
257
|
-
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 };
|
|
296
|
+
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 CacheAdapterStats, type CacheAreaStats, type CachedItemContent, type CachedItemList, type CachedItemMeta, type CheckResult, type CollectionCacheOps, type CollectionClient, type ContentBlock, type ContentConfig, type ContentResult, type CreateClientOptions, DEFAULT_RATE_LIMITER, 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 LogContext, 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 StrictCollectionDef, type WarmOptions, type WarmResult, type WebhookConfig, createClient, createHandler, defineCollection, definePlugin, isCMSError, isCMSErrorInNamespace, isStale, matchCMSError, memoryCache, mergeHooks, mergeLoggers, nodePreset, noopDocOps, noopImgOps, sha256Hex, withRetry };
|
|
258
297
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { memoryCache } from "./cache/memory.mjs";
|
|
2
2
|
import { CMSError, isCMSError, isCMSErrorInNamespace, matchCMSError } from "./errors.mjs";
|
|
3
|
-
import { mergeHooks, mergeLoggers } from "./hooks.mjs";
|
|
3
|
+
import { mergeHooks, mergeLoggers, withTraceId } from "./hooks.mjs";
|
|
4
4
|
import { nodePreset } from "./preset/node.mjs";
|
|
5
5
|
//#region src/cache.ts
|
|
6
6
|
/** 文字列をSHA-256でハッシュ化し、16進数文字列として返す。画像キーの生成に使用。 */
|
|
@@ -314,9 +314,9 @@ async function withRetry(fn, config) {
|
|
|
314
314
|
if (status === void 0 || !config.retryOn.includes(status)) throw err;
|
|
315
315
|
lastError = err;
|
|
316
316
|
if (attempt < config.maxRetries) {
|
|
317
|
-
config.onRetry?.(attempt + 1, status);
|
|
318
317
|
const jitterFactor = config.jitter !== false ? .5 + Math.random() * .5 : 1;
|
|
319
318
|
const delay = config.baseDelayMs * 2 ** attempt * jitterFactor;
|
|
319
|
+
config.onRetry?.(attempt + 1, status, delay);
|
|
320
320
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
321
321
|
}
|
|
322
322
|
}
|
|
@@ -543,7 +543,20 @@ var CollectionClientImpl = class {
|
|
|
543
543
|
html: async () => (await loadPayload()).html,
|
|
544
544
|
markdown: async () => (await loadPayload()).markdown,
|
|
545
545
|
blocks: async () => (await loadPayload()).blocks,
|
|
546
|
-
notionBlocks: async () =>
|
|
546
|
+
notionBlocks: async () => {
|
|
547
|
+
const notionBlocks = (await loadPayload()).notionBlocks;
|
|
548
|
+
if (notionBlocks === void 0) this.warnMissingNotionBlocks();
|
|
549
|
+
return notionBlocks;
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
notionBlocksWarned = false;
|
|
554
|
+
warnMissingNotionBlocks() {
|
|
555
|
+
if (this.notionBlocksWarned) return;
|
|
556
|
+
this.notionBlocksWarned = true;
|
|
557
|
+
this.ctx.logger?.warn?.("notionBlocks() が undefined を返しました。BlockObjectResponse ツリーは blocks 戦略でのみ得られます (notionSource の fetch 未指定の既定でも有効)。markdownFetcher を使用中の場合は markdown→React の Renderer を使うか、blocksFetcher() に切り替えてください。", {
|
|
558
|
+
collection: this.ctx.collection,
|
|
559
|
+
operation: "notionBlocks"
|
|
547
560
|
});
|
|
548
561
|
}
|
|
549
562
|
async fetchList() {
|
|
@@ -683,10 +696,11 @@ var CollectionClientImpl = class {
|
|
|
683
696
|
async fetchListRaw() {
|
|
684
697
|
return (await withRetry(() => this.ctx.source.list({ publishedStatuses: this.ctx.publishedStatuses.length > 0 ? this.ctx.publishedStatuses : void 0 }), {
|
|
685
698
|
...this.ctx.retryConfig,
|
|
686
|
-
onRetry: (attempt, status) => {
|
|
699
|
+
onRetry: (attempt, status, delayMs) => {
|
|
687
700
|
this.ctx.logger?.warn?.("list() リトライ中", {
|
|
688
701
|
attempt,
|
|
689
|
-
status
|
|
702
|
+
status,
|
|
703
|
+
backoffMs: delayMs
|
|
690
704
|
});
|
|
691
705
|
}
|
|
692
706
|
})).filter((item) => {
|
|
@@ -698,11 +712,12 @@ var CollectionClientImpl = class {
|
|
|
698
712
|
async fetchRaw(slug) {
|
|
699
713
|
const retryOpts = {
|
|
700
714
|
...this.ctx.retryConfig,
|
|
701
|
-
onRetry: (attempt, status) => {
|
|
715
|
+
onRetry: (attempt, status, delayMs) => {
|
|
702
716
|
this.ctx.logger?.warn?.("find() リトライ中", {
|
|
703
717
|
attempt,
|
|
704
718
|
status,
|
|
705
|
-
slug
|
|
719
|
+
slug,
|
|
720
|
+
backoffMs: delayMs
|
|
706
721
|
});
|
|
707
722
|
}
|
|
708
723
|
};
|
|
@@ -870,35 +885,49 @@ function trimTrailingSlash(s) {
|
|
|
870
885
|
const DEFAULT_IMAGE_PROXY_BASE = "/api/images";
|
|
871
886
|
/**
|
|
872
887
|
* adapter の `handles` を見て先勝ちで document / image を割り当てる。未指定は両方 noop。
|
|
888
|
+
* `cms.stats()` から元 adapter の `stats()` を呼びたいので、解決元 adapter も保持する。
|
|
873
889
|
*/
|
|
874
890
|
function resolveCache(cache) {
|
|
875
891
|
const adapters = cache ?? [];
|
|
876
892
|
let doc = noopDocOps;
|
|
877
893
|
let docName = "noop-document";
|
|
894
|
+
let docAdapter;
|
|
878
895
|
let img = noopImgOps;
|
|
879
896
|
let imgName = "noop-image";
|
|
897
|
+
let imgAdapter;
|
|
880
898
|
let docFound = false;
|
|
881
899
|
let imgFound = false;
|
|
882
900
|
for (const adapter of adapters) {
|
|
883
901
|
if (!docFound && adapter.handles.includes("document") && adapter.doc) {
|
|
884
902
|
doc = adapter.doc;
|
|
885
903
|
docName = adapter.name;
|
|
904
|
+
docAdapter = adapter;
|
|
886
905
|
docFound = true;
|
|
887
906
|
}
|
|
888
907
|
if (!imgFound && adapter.handles.includes("image") && adapter.img) {
|
|
889
908
|
img = adapter.img;
|
|
890
909
|
imgName = adapter.name;
|
|
910
|
+
imgAdapter = adapter;
|
|
891
911
|
imgFound = true;
|
|
892
912
|
}
|
|
893
913
|
}
|
|
894
914
|
return {
|
|
895
915
|
doc,
|
|
896
916
|
docName,
|
|
917
|
+
docAdapter,
|
|
897
918
|
img,
|
|
898
919
|
imgName,
|
|
920
|
+
imgAdapter,
|
|
899
921
|
hasImg: imgFound
|
|
900
922
|
};
|
|
901
923
|
}
|
|
924
|
+
/**
|
|
925
|
+
* 衝突しにくい短い trace ID を生成する。`{epoch36}-{rand36}` の 10〜12 文字程度。
|
|
926
|
+
* core はゼロ依存ルールに従い node:crypto を静的 import しないため、Math.random ベースで十分。
|
|
927
|
+
*/
|
|
928
|
+
function generateTraceId() {
|
|
929
|
+
return `${Date.now().toString(36)}-${Math.floor(Math.random() * 36 ** 6).toString(36).padStart(6, "0")}`;
|
|
930
|
+
}
|
|
902
931
|
const LOG_LEVEL_ORDER = {
|
|
903
932
|
debug: 0,
|
|
904
933
|
info: 1,
|
|
@@ -971,7 +1000,9 @@ function createClient(opts) {
|
|
|
971
1000
|
const rendererFn = opts.renderer;
|
|
972
1001
|
const waitUntil = opts.waitUntil;
|
|
973
1002
|
const baseLogger = mergeLoggers(opts.plugins ?? [], opts.logger);
|
|
974
|
-
const
|
|
1003
|
+
const traceId = generateTraceId();
|
|
1004
|
+
const tracedLogger = withTraceId(baseLogger, traceId);
|
|
1005
|
+
const logger = opts.logLevel ? applyLogLevel(tracedLogger, opts.logLevel) : tracedLogger;
|
|
975
1006
|
const hooks = mergeHooks(opts.plugins ?? [], opts.hooks, logger);
|
|
976
1007
|
const maxConcurrent = opts.rateLimiter?.maxConcurrent ?? 3;
|
|
977
1008
|
const retryConfig = {
|
|
@@ -1020,6 +1051,45 @@ function createClient(opts) {
|
|
|
1020
1051
|
collections: collectionNames,
|
|
1021
1052
|
cacheImage: cacheRes.hasImg ? buildCacheImageFn(cacheRes.img, cacheRes.imgName, imageProxyBase, logger) : void 0,
|
|
1022
1053
|
imageProxyBase,
|
|
1054
|
+
traceId,
|
|
1055
|
+
async stats() {
|
|
1056
|
+
const stats = { traceId };
|
|
1057
|
+
const adapterCache = /* @__PURE__ */ new Map();
|
|
1058
|
+
const ensure = (adapter) => {
|
|
1059
|
+
if (!adapter?.stats) return void 0;
|
|
1060
|
+
const cached = adapterCache.get(adapter);
|
|
1061
|
+
if (cached) return cached;
|
|
1062
|
+
const fresh = adapter.stats();
|
|
1063
|
+
adapterCache.set(adapter, fresh);
|
|
1064
|
+
return fresh;
|
|
1065
|
+
};
|
|
1066
|
+
const docPromise = ensure(cacheRes.docAdapter);
|
|
1067
|
+
const imgPromise = ensure(cacheRes.imgAdapter);
|
|
1068
|
+
const computeHitRate = (h, m) => h + m === 0 ? 0 : h / (h + m);
|
|
1069
|
+
if (docPromise) {
|
|
1070
|
+
const docStats = await docPromise;
|
|
1071
|
+
if (docStats.doc) stats.document = {
|
|
1072
|
+
adapter: docStats.name ?? cacheRes.docName,
|
|
1073
|
+
hits: docStats.doc.hits,
|
|
1074
|
+
misses: docStats.doc.misses,
|
|
1075
|
+
entries: docStats.doc.entries,
|
|
1076
|
+
sizeBytes: docStats.doc.sizeBytes,
|
|
1077
|
+
hitRate: computeHitRate(docStats.doc.hits, docStats.doc.misses)
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
if (imgPromise) {
|
|
1081
|
+
const imgStats = await imgPromise;
|
|
1082
|
+
if (imgStats.img) stats.image = {
|
|
1083
|
+
adapter: imgStats.name ?? cacheRes.imgName,
|
|
1084
|
+
hits: imgStats.img.hits,
|
|
1085
|
+
misses: imgStats.img.misses,
|
|
1086
|
+
entries: imgStats.img.entries,
|
|
1087
|
+
sizeBytes: imgStats.img.sizeBytes,
|
|
1088
|
+
hitRate: computeHitRate(imgStats.img.hits, imgStats.img.misses)
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
return stats;
|
|
1092
|
+
},
|
|
1023
1093
|
async invalidate(scope) {
|
|
1024
1094
|
logger?.debug?.("グローバルキャッシュを無効化", {
|
|
1025
1095
|
operation: "invalidate",
|
|
@@ -1061,11 +1131,48 @@ function createClient(opts) {
|
|
|
1061
1131
|
return Object.assign(Object.create(null), collections, globalOps);
|
|
1062
1132
|
}
|
|
1063
1133
|
//#endregion
|
|
1134
|
+
//#region src/types/config.ts
|
|
1135
|
+
/**
|
|
1136
|
+
* `RateLimiterConfig` のデフォルト値 (Issue #313 / M2)。
|
|
1137
|
+
* 型からだけでは見えない既定値を表面化することで、IDE 補完と
|
|
1138
|
+
* preset の対称化 (`nodePreset` / `cloudflarePreset` / `nextPreset`) で
|
|
1139
|
+
* 同じ既定が適用されることを保証する。
|
|
1140
|
+
*/
|
|
1141
|
+
const DEFAULT_RATE_LIMITER = {
|
|
1142
|
+
maxConcurrent: 3,
|
|
1143
|
+
retryOn: [
|
|
1144
|
+
429,
|
|
1145
|
+
502,
|
|
1146
|
+
503
|
|
1147
|
+
],
|
|
1148
|
+
maxRetries: 4,
|
|
1149
|
+
baseDelayMs: 1e3
|
|
1150
|
+
};
|
|
1151
|
+
/**
|
|
1152
|
+
* 型推論ヘルパー: `T` を明示してコレクション定義を作る。`slugField` / `statusField` は
|
|
1153
|
+
* `keyof T & string` で補完・型ガードされ、誤フィールド名 (例: `"slag"`) で型エラーになる
|
|
1154
|
+
* (Issue #314 / M3)。CLI 生成 `nhc.schema.ts` で利用される。
|
|
1155
|
+
*
|
|
1156
|
+
* @example
|
|
1157
|
+
* ```ts
|
|
1158
|
+
* type PostItem = BaseContentItem & { authorName?: string };
|
|
1159
|
+
* const posts = defineCollection<PostItem>({
|
|
1160
|
+
* source: notionSource(...),
|
|
1161
|
+
* slugField: "slug", // OK
|
|
1162
|
+
* statusField: "status", // OK
|
|
1163
|
+
* // statusField: "stat", // 型エラー
|
|
1164
|
+
* });
|
|
1165
|
+
* ```
|
|
1166
|
+
*/
|
|
1167
|
+
function defineCollection(def) {
|
|
1168
|
+
return def;
|
|
1169
|
+
}
|
|
1170
|
+
//#endregion
|
|
1064
1171
|
//#region src/types/plugin.ts
|
|
1065
1172
|
function definePlugin(plugin) {
|
|
1066
1173
|
return plugin;
|
|
1067
1174
|
}
|
|
1068
1175
|
//#endregion
|
|
1069
|
-
export { CMSError, DEFAULT_RETRY_CONFIG, createClient, createHandler, definePlugin, isCMSError, isCMSErrorInNamespace, isStale, matchCMSError, memoryCache, mergeHooks, mergeLoggers, nodePreset, noopDocOps, noopImgOps, sha256Hex, withRetry };
|
|
1176
|
+
export { CMSError, DEFAULT_RATE_LIMITER, DEFAULT_RETRY_CONFIG, createClient, createHandler, defineCollection, definePlugin, isCMSError, isCMSErrorInNamespace, isStale, matchCMSError, memoryCache, mergeHooks, mergeLoggers, nodePreset, noopDocOps, noopImgOps, sha256Hex, withRetry };
|
|
1070
1177
|
|
|
1071
1178
|
//# sourceMappingURL=index.mjs.map
|