@notion-headless-cms/core 0.1.2 → 0.1.3
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/dist/cache/memory.d.mts +52 -0
- package/dist/cache/memory.mjs +112 -0
- package/dist/cache/memory.mjs.map +1 -0
- package/dist/cache/{noop.d.ts → noop.d.mts} +5 -3
- package/dist/cache/noop.mjs +44 -0
- package/dist/cache/noop.mjs.map +1 -0
- package/dist/cache-B-MG4yyg.d.mts +45 -0
- package/dist/content-BrwEY2_p.d.mts +53 -0
- package/dist/{errors.d.ts → errors.d.mts} +18 -16
- package/dist/errors.mjs +24 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/hooks-DCSAQkST.d.mts +60 -0
- package/dist/hooks.d.mts +2 -0
- package/dist/hooks.mjs +75 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/index.d.mts +449 -0
- package/dist/index.mjs +616 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +17 -16
- package/dist/cache/memory.d.ts +0 -54
- package/dist/cache/memory.js +0 -15
- package/dist/cache/memory.js.map +0 -1
- package/dist/cache/noop.js +0 -9
- package/dist/cache/noop.js.map +0 -1
- package/dist/cache-DvbyemBK.d.ts +0 -33
- package/dist/chunk-4KGKWKKI.js +0 -80
- package/dist/chunk-4KGKWKKI.js.map +0 -1
- package/dist/chunk-6DG63XUF.js +0 -42
- package/dist/chunk-6DG63XUF.js.map +0 -1
- package/dist/chunk-6LHROEPI.js +0 -104
- package/dist/chunk-6LHROEPI.js.map +0 -1
- package/dist/chunk-V6ML4QE5.js +0 -26
- package/dist/chunk-V6ML4QE5.js.map +0 -1
- package/dist/content-Biqf0l_o.d.ts +0 -51
- package/dist/errors.js +0 -11
- package/dist/errors.js.map +0 -1
- package/dist/hooks-B83RUclt.d.ts +0 -41
- package/dist/hooks.d.ts +0 -2
- package/dist/hooks.js +0 -9
- package/dist/hooks.js.map +0 -1
- package/dist/index.d.ts +0 -278
- package/dist/index.js +0 -598
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { a as StorageBinary, i as CachedItemList, r as CachedItem, t as BaseContentItem } from "../content-BrwEY2_p.mjs";
|
|
2
|
+
import { i as InvalidateScope, n as DocumentCacheAdapter, r as ImageCacheAdapter } from "../cache-B-MG4yyg.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/cache/memory.d.ts
|
|
5
|
+
interface MemoryDocumentCacheOptions {
|
|
6
|
+
/** アイテム保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
7
|
+
maxItems?: number;
|
|
8
|
+
}
|
|
9
|
+
interface MemoryImageCacheOptions {
|
|
10
|
+
/** エントリ保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
11
|
+
maxItems?: number;
|
|
12
|
+
/** 合計保持サイズ上限(バイト)。未指定時は上限なし。超過時は LRU で古いものから削除。 */
|
|
13
|
+
maxSizeBytes?: number;
|
|
14
|
+
}
|
|
15
|
+
/** インメモリのドキュメントキャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
|
|
16
|
+
declare class MemoryDocumentCache<T extends BaseContentItem = BaseContentItem> implements DocumentCacheAdapter<T> {
|
|
17
|
+
readonly name = "memory-document";
|
|
18
|
+
private list;
|
|
19
|
+
private items;
|
|
20
|
+
private readonly maxItems;
|
|
21
|
+
constructor(options?: MemoryDocumentCacheOptions);
|
|
22
|
+
getList(): Promise<CachedItemList<T> | null>;
|
|
23
|
+
setList(data: CachedItemList<T>): Promise<void>;
|
|
24
|
+
getItem(slug: string): Promise<CachedItem<T> | null>;
|
|
25
|
+
setItem(slug: string, data: CachedItem<T>): Promise<void>;
|
|
26
|
+
invalidate(scope: InvalidateScope): Promise<void>;
|
|
27
|
+
private enforceLimit;
|
|
28
|
+
}
|
|
29
|
+
/** インメモリの画像キャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
|
|
30
|
+
declare class MemoryImageCache implements ImageCacheAdapter {
|
|
31
|
+
readonly name = "memory-image";
|
|
32
|
+
private store;
|
|
33
|
+
private totalBytes;
|
|
34
|
+
private readonly maxItems;
|
|
35
|
+
private readonly maxSizeBytes;
|
|
36
|
+
constructor(options?: MemoryImageCacheOptions);
|
|
37
|
+
get(hash: string): Promise<StorageBinary | null>;
|
|
38
|
+
set(hash: string, data: ArrayBuffer, contentType: string): Promise<void>;
|
|
39
|
+
private enforceLimit;
|
|
40
|
+
}
|
|
41
|
+
/** インメモリキャッシュ(ドキュメント用)を生成する。 */
|
|
42
|
+
declare function memoryDocumentCache<T extends BaseContentItem = BaseContentItem>(options?: MemoryDocumentCacheOptions): DocumentCacheAdapter<T>;
|
|
43
|
+
/** インメモリキャッシュ(画像用)を生成する。 */
|
|
44
|
+
declare function memoryImageCache(options?: MemoryImageCacheOptions): ImageCacheAdapter;
|
|
45
|
+
/**
|
|
46
|
+
* ドキュメントと画像の両方にインメモリキャッシュを返す便利関数。
|
|
47
|
+
* memoryCache() はドキュメントキャッシュを返す(後方互換)。
|
|
48
|
+
*/
|
|
49
|
+
declare function memoryCache<T extends BaseContentItem = BaseContentItem>(options?: MemoryDocumentCacheOptions): DocumentCacheAdapter<T>;
|
|
50
|
+
//#endregion
|
|
51
|
+
export { MemoryDocumentCache, MemoryDocumentCacheOptions, MemoryImageCache, MemoryImageCacheOptions, memoryCache, memoryDocumentCache, memoryImageCache };
|
|
52
|
+
//# sourceMappingURL=memory.d.mts.map
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/cache/memory.ts
|
|
2
|
+
/**
|
|
3
|
+
* Map の挿入順を LRU として扱う軽量実装。
|
|
4
|
+
* `touch` で既存キーを末尾に移動、`enforceLimit` で古いキー(先頭)から削除する。
|
|
5
|
+
*/
|
|
6
|
+
function touch(map, key) {
|
|
7
|
+
const v = map.get(key);
|
|
8
|
+
if (v === void 0) return;
|
|
9
|
+
map.delete(key);
|
|
10
|
+
map.set(key, v);
|
|
11
|
+
}
|
|
12
|
+
/** インメモリのドキュメントキャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
|
|
13
|
+
var MemoryDocumentCache = class {
|
|
14
|
+
name = "memory-document";
|
|
15
|
+
list = null;
|
|
16
|
+
items = /* @__PURE__ */ new Map();
|
|
17
|
+
maxItems;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.maxItems = options?.maxItems;
|
|
20
|
+
}
|
|
21
|
+
getList() {
|
|
22
|
+
return Promise.resolve(this.list);
|
|
23
|
+
}
|
|
24
|
+
setList(data) {
|
|
25
|
+
this.list = data;
|
|
26
|
+
return Promise.resolve();
|
|
27
|
+
}
|
|
28
|
+
getItem(slug) {
|
|
29
|
+
const entry = this.items.get(slug);
|
|
30
|
+
if (entry) touch(this.items, slug);
|
|
31
|
+
return Promise.resolve(entry ?? null);
|
|
32
|
+
}
|
|
33
|
+
setItem(slug, data) {
|
|
34
|
+
if (this.items.has(slug)) this.items.delete(slug);
|
|
35
|
+
this.items.set(slug, data);
|
|
36
|
+
this.enforceLimit();
|
|
37
|
+
return Promise.resolve();
|
|
38
|
+
}
|
|
39
|
+
async invalidate(scope) {
|
|
40
|
+
if (scope === "all") {
|
|
41
|
+
this.list = null;
|
|
42
|
+
this.items.clear();
|
|
43
|
+
} else if ("slug" in scope) this.items.delete(scope.slug);
|
|
44
|
+
}
|
|
45
|
+
enforceLimit() {
|
|
46
|
+
if (this.maxItems === void 0) return;
|
|
47
|
+
while (this.items.size > this.maxItems) {
|
|
48
|
+
const firstKey = this.items.keys().next().value;
|
|
49
|
+
if (firstKey === void 0) break;
|
|
50
|
+
this.items.delete(firstKey);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
/** インメモリの画像キャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
|
|
55
|
+
var MemoryImageCache = class {
|
|
56
|
+
name = "memory-image";
|
|
57
|
+
store = /* @__PURE__ */ new Map();
|
|
58
|
+
totalBytes = 0;
|
|
59
|
+
maxItems;
|
|
60
|
+
maxSizeBytes;
|
|
61
|
+
constructor(options) {
|
|
62
|
+
this.maxItems = options?.maxItems;
|
|
63
|
+
this.maxSizeBytes = options?.maxSizeBytes;
|
|
64
|
+
}
|
|
65
|
+
get(hash) {
|
|
66
|
+
const entry = this.store.get(hash);
|
|
67
|
+
if (entry) touch(this.store, hash);
|
|
68
|
+
return Promise.resolve(entry ?? null);
|
|
69
|
+
}
|
|
70
|
+
set(hash, data, contentType) {
|
|
71
|
+
const existing = this.store.get(hash);
|
|
72
|
+
if (existing) {
|
|
73
|
+
this.totalBytes -= existing.data.byteLength;
|
|
74
|
+
this.store.delete(hash);
|
|
75
|
+
}
|
|
76
|
+
this.store.set(hash, {
|
|
77
|
+
data,
|
|
78
|
+
contentType
|
|
79
|
+
});
|
|
80
|
+
this.totalBytes += data.byteLength;
|
|
81
|
+
this.enforceLimit();
|
|
82
|
+
return Promise.resolve();
|
|
83
|
+
}
|
|
84
|
+
enforceLimit() {
|
|
85
|
+
while (this.maxItems !== void 0 && this.store.size > this.maxItems || this.maxSizeBytes !== void 0 && this.totalBytes > this.maxSizeBytes) {
|
|
86
|
+
const firstKey = this.store.keys().next().value;
|
|
87
|
+
if (firstKey === void 0) break;
|
|
88
|
+
const victim = this.store.get(firstKey);
|
|
89
|
+
if (victim) this.totalBytes -= victim.data.byteLength;
|
|
90
|
+
this.store.delete(firstKey);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
/** インメモリキャッシュ(ドキュメント用)を生成する。 */
|
|
95
|
+
function memoryDocumentCache(options) {
|
|
96
|
+
return new MemoryDocumentCache(options);
|
|
97
|
+
}
|
|
98
|
+
/** インメモリキャッシュ(画像用)を生成する。 */
|
|
99
|
+
function memoryImageCache(options) {
|
|
100
|
+
return new MemoryImageCache(options);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* ドキュメントと画像の両方にインメモリキャッシュを返す便利関数。
|
|
104
|
+
* memoryCache() はドキュメントキャッシュを返す(後方互換)。
|
|
105
|
+
*/
|
|
106
|
+
function memoryCache(options) {
|
|
107
|
+
return new MemoryDocumentCache(options);
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
export { MemoryDocumentCache, MemoryImageCache, memoryCache, memoryDocumentCache, memoryImageCache };
|
|
111
|
+
|
|
112
|
+
//# sourceMappingURL=memory.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.mjs","names":[],"sources":["../../src/cache/memory.ts"],"sourcesContent":["import type {\n\tBaseContentItem,\n\tCachedItem,\n\tCachedItemList,\n\tCacheInvalidateScope,\n\tDocumentCacheAdapter,\n\tImageCacheAdapter,\n\tStorageBinary,\n} from \"../types/index\";\n\nexport interface MemoryDocumentCacheOptions {\n\t/** アイテム保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */\n\tmaxItems?: number;\n}\n\nexport interface MemoryImageCacheOptions {\n\t/** エントリ保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */\n\tmaxItems?: number;\n\t/** 合計保持サイズ上限(バイト)。未指定時は上限なし。超過時は LRU で古いものから削除。 */\n\tmaxSizeBytes?: number;\n}\n\n/**\n * Map の挿入順を LRU として扱う軽量実装。\n * `touch` で既存キーを末尾に移動、`enforceLimit` で古いキー(先頭)から削除する。\n */\nfunction touch<K, V>(map: Map<K, V>, key: K): void {\n\tconst v = map.get(key);\n\tif (v === undefined) return;\n\tmap.delete(key);\n\tmap.set(key, v);\n}\n\n/** インメモリのドキュメントキャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */\nexport class MemoryDocumentCache<T extends BaseContentItem = BaseContentItem>\n\timplements DocumentCacheAdapter<T>\n{\n\treadonly name = \"memory-document\";\n\tprivate list: CachedItemList<T> | null = null;\n\tprivate items = new Map<string, CachedItem<T>>();\n\tprivate readonly maxItems: number | undefined;\n\n\tconstructor(options?: MemoryDocumentCacheOptions) {\n\t\tthis.maxItems = options?.maxItems;\n\t}\n\n\tgetList(): Promise<CachedItemList<T> | null> {\n\t\treturn Promise.resolve(this.list);\n\t}\n\n\tsetList(data: CachedItemList<T>): Promise<void> {\n\t\tthis.list = data;\n\t\treturn Promise.resolve();\n\t}\n\n\tgetItem(slug: string): Promise<CachedItem<T> | null> {\n\t\tconst entry = this.items.get(slug);\n\t\tif (entry) touch(this.items, slug);\n\t\treturn Promise.resolve(entry ?? null);\n\t}\n\n\tsetItem(slug: string, data: CachedItem<T>): Promise<void> {\n\t\tif (this.items.has(slug)) this.items.delete(slug);\n\t\tthis.items.set(slug, data);\n\t\tthis.enforceLimit();\n\t\treturn Promise.resolve();\n\t}\n\n\tasync invalidate(scope: CacheInvalidateScope): Promise<void> {\n\t\tif (scope === \"all\") {\n\t\t\tthis.list = null;\n\t\t\tthis.items.clear();\n\t\t} else if (\"slug\" in scope) {\n\t\t\tthis.items.delete(scope.slug);\n\t\t}\n\t}\n\n\tprivate enforceLimit(): void {\n\t\tif (this.maxItems === undefined) return;\n\t\twhile (this.items.size > this.maxItems) {\n\t\t\tconst firstKey = this.items.keys().next().value;\n\t\t\tif (firstKey === undefined) break;\n\t\t\tthis.items.delete(firstKey);\n\t\t}\n\t}\n}\n\n/** インメモリの画像キャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */\nexport class MemoryImageCache implements ImageCacheAdapter {\n\treadonly name = \"memory-image\";\n\tprivate store = new Map<string, StorageBinary>();\n\tprivate totalBytes = 0;\n\tprivate readonly maxItems: number | undefined;\n\tprivate readonly maxSizeBytes: number | undefined;\n\n\tconstructor(options?: MemoryImageCacheOptions) {\n\t\tthis.maxItems = options?.maxItems;\n\t\tthis.maxSizeBytes = options?.maxSizeBytes;\n\t}\n\n\tget(hash: string): Promise<StorageBinary | null> {\n\t\tconst entry = this.store.get(hash);\n\t\tif (entry) touch(this.store, hash);\n\t\treturn Promise.resolve(entry ?? null);\n\t}\n\n\tset(hash: string, data: ArrayBuffer, contentType: string): Promise<void> {\n\t\tconst existing = this.store.get(hash);\n\t\tif (existing) {\n\t\t\tthis.totalBytes -= existing.data.byteLength;\n\t\t\tthis.store.delete(hash);\n\t\t}\n\t\tthis.store.set(hash, { data, contentType });\n\t\tthis.totalBytes += data.byteLength;\n\t\tthis.enforceLimit();\n\t\treturn Promise.resolve();\n\t}\n\n\tprivate enforceLimit(): void {\n\t\twhile (\n\t\t\t(this.maxItems !== undefined && this.store.size > this.maxItems) ||\n\t\t\t(this.maxSizeBytes !== undefined && this.totalBytes > this.maxSizeBytes)\n\t\t) {\n\t\t\tconst firstKey = this.store.keys().next().value;\n\t\t\tif (firstKey === undefined) break;\n\t\t\tconst victim = this.store.get(firstKey);\n\t\t\tif (victim) this.totalBytes -= victim.data.byteLength;\n\t\t\tthis.store.delete(firstKey);\n\t\t}\n\t}\n}\n\n/** インメモリキャッシュ(ドキュメント用)を生成する。 */\nexport function memoryDocumentCache<\n\tT extends BaseContentItem = BaseContentItem,\n>(options?: MemoryDocumentCacheOptions): DocumentCacheAdapter<T> {\n\treturn new MemoryDocumentCache<T>(options);\n}\n\n/** インメモリキャッシュ(画像用)を生成する。 */\nexport function memoryImageCache(\n\toptions?: MemoryImageCacheOptions,\n): ImageCacheAdapter {\n\treturn new MemoryImageCache(options);\n}\n\n/**\n * ドキュメントと画像の両方にインメモリキャッシュを返す便利関数。\n * memoryCache() はドキュメントキャッシュを返す(後方互換)。\n */\nexport function memoryCache<T extends BaseContentItem = BaseContentItem>(\n\toptions?: MemoryDocumentCacheOptions,\n): DocumentCacheAdapter<T> {\n\treturn new MemoryDocumentCache<T>(options);\n}\n"],"mappings":";;;;;AA0BA,SAAS,MAAY,KAAgB,KAAc;CAClD,MAAM,IAAI,IAAI,IAAI,IAAI;AACtB,KAAI,MAAM,KAAA,EAAW;AACrB,KAAI,OAAO,IAAI;AACf,KAAI,IAAI,KAAK,EAAE;;;AAIhB,IAAa,sBAAb,MAEA;CACC,OAAgB;CAChB,OAAyC;CACzC,wBAAgB,IAAI,KAA4B;CAChD;CAEA,YAAY,SAAsC;AACjD,OAAK,WAAW,SAAS;;CAG1B,UAA6C;AAC5C,SAAO,QAAQ,QAAQ,KAAK,KAAK;;CAGlC,QAAQ,MAAwC;AAC/C,OAAK,OAAO;AACZ,SAAO,QAAQ,SAAS;;CAGzB,QAAQ,MAA6C;EACpD,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK;AAClC,MAAI,MAAO,OAAM,KAAK,OAAO,KAAK;AAClC,SAAO,QAAQ,QAAQ,SAAS,KAAK;;CAGtC,QAAQ,MAAc,MAAoC;AACzD,MAAI,KAAK,MAAM,IAAI,KAAK,CAAE,MAAK,MAAM,OAAO,KAAK;AACjD,OAAK,MAAM,IAAI,MAAM,KAAK;AAC1B,OAAK,cAAc;AACnB,SAAO,QAAQ,SAAS;;CAGzB,MAAM,WAAW,OAA4C;AAC5D,MAAI,UAAU,OAAO;AACpB,QAAK,OAAO;AACZ,QAAK,MAAM,OAAO;aACR,UAAU,MACpB,MAAK,MAAM,OAAO,MAAM,KAAK;;CAI/B,eAA6B;AAC5B,MAAI,KAAK,aAAa,KAAA,EAAW;AACjC,SAAO,KAAK,MAAM,OAAO,KAAK,UAAU;GACvC,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC;AAC1C,OAAI,aAAa,KAAA,EAAW;AAC5B,QAAK,MAAM,OAAO,SAAS;;;;;AAM9B,IAAa,mBAAb,MAA2D;CAC1D,OAAgB;CAChB,wBAAgB,IAAI,KAA4B;CAChD,aAAqB;CACrB;CACA;CAEA,YAAY,SAAmC;AAC9C,OAAK,WAAW,SAAS;AACzB,OAAK,eAAe,SAAS;;CAG9B,IAAI,MAA6C;EAChD,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK;AAClC,MAAI,MAAO,OAAM,KAAK,OAAO,KAAK;AAClC,SAAO,QAAQ,QAAQ,SAAS,KAAK;;CAGtC,IAAI,MAAc,MAAmB,aAAoC;EACxE,MAAM,WAAW,KAAK,MAAM,IAAI,KAAK;AACrC,MAAI,UAAU;AACb,QAAK,cAAc,SAAS,KAAK;AACjC,QAAK,MAAM,OAAO,KAAK;;AAExB,OAAK,MAAM,IAAI,MAAM;GAAE;GAAM;GAAa,CAAC;AAC3C,OAAK,cAAc,KAAK;AACxB,OAAK,cAAc;AACnB,SAAO,QAAQ,SAAS;;CAGzB,eAA6B;AAC5B,SACE,KAAK,aAAa,KAAA,KAAa,KAAK,MAAM,OAAO,KAAK,YACtD,KAAK,iBAAiB,KAAA,KAAa,KAAK,aAAa,KAAK,cAC1D;GACD,MAAM,WAAW,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC;AAC1C,OAAI,aAAa,KAAA,EAAW;GAC5B,MAAM,SAAS,KAAK,MAAM,IAAI,SAAS;AACvC,OAAI,OAAQ,MAAK,cAAc,OAAO,KAAK;AAC3C,QAAK,MAAM,OAAO,SAAS;;;;;AAM9B,SAAgB,oBAEd,SAA+D;AAChE,QAAO,IAAI,oBAAuB,QAAQ;;;AAI3C,SAAgB,iBACf,SACoB;AACpB,QAAO,IAAI,iBAAiB,QAAQ;;;;;;AAOrC,SAAgB,YACf,SAC0B;AAC1B,QAAO,IAAI,oBAAuB,QAAQ"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { t as BaseContentItem } from "../content-BrwEY2_p.mjs";
|
|
2
|
+
import { n as DocumentCacheAdapter, r as ImageCacheAdapter } from "../cache-B-MG4yyg.mjs";
|
|
3
3
|
|
|
4
|
+
//#region src/cache/noop.d.ts
|
|
4
5
|
/** 何もしないドキュメントキャッシュを返す(シングルトン)。 */
|
|
5
6
|
declare function noopDocumentCache<T extends BaseContentItem = BaseContentItem>(): DocumentCacheAdapter<T>;
|
|
6
7
|
/** 何もしない画像キャッシュを返す(シングルトン)。 */
|
|
7
8
|
declare function noopImageCache(): ImageCacheAdapter;
|
|
8
|
-
|
|
9
|
+
//#endregion
|
|
9
10
|
export { noopDocumentCache, noopImageCache };
|
|
11
|
+
//# sourceMappingURL=noop.d.mts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//#region src/cache/noop.ts
|
|
2
|
+
/** 何もキャッシュしないドキュメントキャッシュ実装。常に null を返す。 */
|
|
3
|
+
var NoopDocumentCache = class {
|
|
4
|
+
name = "noop-document";
|
|
5
|
+
getList() {
|
|
6
|
+
return Promise.resolve(null);
|
|
7
|
+
}
|
|
8
|
+
setList(_data) {
|
|
9
|
+
return Promise.resolve();
|
|
10
|
+
}
|
|
11
|
+
getItem(_slug) {
|
|
12
|
+
return Promise.resolve(null);
|
|
13
|
+
}
|
|
14
|
+
setItem(_slug, _data) {
|
|
15
|
+
return Promise.resolve();
|
|
16
|
+
}
|
|
17
|
+
invalidate(_scope) {
|
|
18
|
+
return Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/** 何もキャッシュしない画像キャッシュ実装。常に null を返す。 */
|
|
22
|
+
var NoopImageCache = class {
|
|
23
|
+
name = "noop-image";
|
|
24
|
+
get(_hash) {
|
|
25
|
+
return Promise.resolve(null);
|
|
26
|
+
}
|
|
27
|
+
set(_hash, _data, _contentType) {
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const _noopDocument = new NoopDocumentCache();
|
|
32
|
+
const _noopImage = new NoopImageCache();
|
|
33
|
+
/** 何もしないドキュメントキャッシュを返す(シングルトン)。 */
|
|
34
|
+
function noopDocumentCache() {
|
|
35
|
+
return _noopDocument;
|
|
36
|
+
}
|
|
37
|
+
/** 何もしない画像キャッシュを返す(シングルトン)。 */
|
|
38
|
+
function noopImageCache() {
|
|
39
|
+
return _noopImage;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { noopDocumentCache, noopImageCache };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=noop.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"noop.mjs","names":[],"sources":["../../src/cache/noop.ts"],"sourcesContent":["import type {\n\tBaseContentItem,\n\tCachedItem,\n\tCachedItemList,\n\tCacheInvalidateScope,\n\tDocumentCacheAdapter,\n\tImageCacheAdapter,\n\tStorageBinary,\n} from \"../types/index\";\n\n/** 何もキャッシュしないドキュメントキャッシュ実装。常に null を返す。 */\nclass NoopDocumentCache<T extends BaseContentItem = BaseContentItem>\n\timplements DocumentCacheAdapter<T>\n{\n\treadonly name = \"noop-document\";\n\n\tgetList(): Promise<CachedItemList<T> | null> {\n\t\treturn Promise.resolve(null);\n\t}\n\n\tsetList(_data: CachedItemList<T>): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n\n\tgetItem(_slug: string): Promise<CachedItem<T> | null> {\n\t\treturn Promise.resolve(null);\n\t}\n\n\tsetItem(_slug: string, _data: CachedItem<T>): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n\n\tinvalidate(_scope: CacheInvalidateScope): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n}\n\n/** 何もキャッシュしない画像キャッシュ実装。常に null を返す。 */\nclass NoopImageCache implements ImageCacheAdapter {\n\treadonly name = \"noop-image\";\n\n\tget(_hash: string): Promise<StorageBinary | null> {\n\t\treturn Promise.resolve(null);\n\t}\n\n\tset(_hash: string, _data: ArrayBuffer, _contentType: string): Promise<void> {\n\t\treturn Promise.resolve();\n\t}\n}\n\nconst _noopDocument = new NoopDocumentCache();\nconst _noopImage = new NoopImageCache();\n\n/** 何もしないドキュメントキャッシュを返す(シングルトン)。 */\nexport function noopDocumentCache<\n\tT extends BaseContentItem = BaseContentItem,\n>(): DocumentCacheAdapter<T> {\n\treturn _noopDocument as DocumentCacheAdapter<T>;\n}\n\n/** 何もしない画像キャッシュを返す(シングルトン)。 */\nexport function noopImageCache(): ImageCacheAdapter {\n\treturn _noopImage;\n}\n"],"mappings":";;AAWA,IAAM,oBAAN,MAEA;CACC,OAAgB;CAEhB,UAA6C;AAC5C,SAAO,QAAQ,QAAQ,KAAK;;CAG7B,QAAQ,OAAyC;AAChD,SAAO,QAAQ,SAAS;;CAGzB,QAAQ,OAA8C;AACrD,SAAO,QAAQ,QAAQ,KAAK;;CAG7B,QAAQ,OAAe,OAAqC;AAC3D,SAAO,QAAQ,SAAS;;CAGzB,WAAW,QAA6C;AACvD,SAAO,QAAQ,SAAS;;;;AAK1B,IAAM,iBAAN,MAAkD;CACjD,OAAgB;CAEhB,IAAI,OAA8C;AACjD,SAAO,QAAQ,QAAQ,KAAK;;CAG7B,IAAI,OAAe,OAAoB,cAAqC;AAC3E,SAAO,QAAQ,SAAS;;;AAI1B,MAAM,gBAAgB,IAAI,mBAAmB;AAC7C,MAAM,aAAa,IAAI,gBAAgB;;AAGvC,SAAgB,oBAEa;AAC5B,QAAO;;;AAIR,SAAgB,iBAAoC;AACnD,QAAO"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { a as StorageBinary, i as CachedItemList, r as CachedItem, t as BaseContentItem } from "./content-BrwEY2_p.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/types/cache.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* キャッシュ無効化のスコープ。
|
|
6
|
+
* v1 API では `{ collection, slug? }` が主形式。
|
|
7
|
+
* 旧 `{ tag }` 形式は後方互換のため残す。
|
|
8
|
+
*/
|
|
9
|
+
type InvalidateScope = "all" | {
|
|
10
|
+
slug: string;
|
|
11
|
+
} | {
|
|
12
|
+
tag: string;
|
|
13
|
+
} | {
|
|
14
|
+
collection: string;
|
|
15
|
+
} | {
|
|
16
|
+
collection: string;
|
|
17
|
+
slug: string;
|
|
18
|
+
};
|
|
19
|
+
/** ドキュメントキャッシュを抽象化するインターフェース。 */
|
|
20
|
+
interface DocumentCacheAdapter<T extends BaseContentItem = BaseContentItem> {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
getList(): Promise<CachedItemList<T> | null>;
|
|
23
|
+
setList(data: CachedItemList<T>): Promise<void>;
|
|
24
|
+
getItem(slug: string): Promise<CachedItem<T> | null>;
|
|
25
|
+
setItem(slug: string, data: CachedItem<T>): Promise<void>;
|
|
26
|
+
invalidate?(scope: InvalidateScope): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
/** 画像キャッシュを抽象化するインターフェース。 */
|
|
29
|
+
interface ImageCacheAdapter {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
get(hash: string): Promise<StorageBinary | null>;
|
|
32
|
+
set(hash: string, data: ArrayBuffer, contentType: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* キャッシュ設定。`"disabled"` を渡すと完全にキャッシュを無効化する。
|
|
36
|
+
* オブジェクトの場合、document / image それぞれ独立したアダプタを差し込める。
|
|
37
|
+
*/
|
|
38
|
+
type CacheConfig<T extends BaseContentItem = BaseContentItem> = "disabled" | {
|
|
39
|
+
document?: DocumentCacheAdapter<T>;
|
|
40
|
+
image?: ImageCacheAdapter; /** キャッシュの有効期間(ミリ秒)。未設定の場合はTTLなし。 */
|
|
41
|
+
ttlMs?: number;
|
|
42
|
+
};
|
|
43
|
+
//#endregion
|
|
44
|
+
export { InvalidateScope as i, DocumentCacheAdapter as n, ImageCacheAdapter as r, CacheConfig as t };
|
|
45
|
+
//# sourceMappingURL=cache-B-MG4yyg.d.mts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/types/content.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* ライブラリが動作するために必須なフィールド。
|
|
4
|
+
* 利用者はこのインターフェースを拡張して独自のコンテンツ型を定義する。
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* interface Post extends BaseContentItem {
|
|
8
|
+
* title: string;
|
|
9
|
+
* author: string;
|
|
10
|
+
* }
|
|
11
|
+
* createCMS<Post>({ source: notionAdapter({ ... }) })
|
|
12
|
+
*/
|
|
13
|
+
interface BaseContentItem {
|
|
14
|
+
/** Notion ページ ID(変更検知に必須)。 */
|
|
15
|
+
id: string;
|
|
16
|
+
/** URL キー(必須)。 */
|
|
17
|
+
slug: string;
|
|
18
|
+
/** 最終更新タイムスタンプ(変更検知に必須)。 */
|
|
19
|
+
updatedAt: string;
|
|
20
|
+
/** コンテンツのステータス。ステータスのない DB では省略可能。 */
|
|
21
|
+
status?: string;
|
|
22
|
+
/** 公開日時。日付プロパティのない DB では省略可能。 */
|
|
23
|
+
publishedAt?: string;
|
|
24
|
+
}
|
|
25
|
+
/** ストレージにキャッシュされたレンダリング済みコンテンツ。 */
|
|
26
|
+
interface CachedItem<T extends BaseContentItem = BaseContentItem> {
|
|
27
|
+
html: string;
|
|
28
|
+
item: T;
|
|
29
|
+
notionUpdatedAt: string;
|
|
30
|
+
cachedAt: number;
|
|
31
|
+
}
|
|
32
|
+
/** ストレージにキャッシュされたコンテンツ一覧。 */
|
|
33
|
+
interface CachedItemList<T extends BaseContentItem = BaseContentItem> {
|
|
34
|
+
items: T[];
|
|
35
|
+
cachedAt: number;
|
|
36
|
+
}
|
|
37
|
+
/** ストレージから取得したバイナリオブジェクト。 */
|
|
38
|
+
interface StorageBinary {
|
|
39
|
+
data: ArrayBuffer;
|
|
40
|
+
contentType?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Notionのプロパティ名マッピング(すべてオプション)。 */
|
|
43
|
+
interface CMSSchemaProperties {
|
|
44
|
+
/** Notionのスラッグプロパティ名。デフォルト: 'Slug' */
|
|
45
|
+
slug?: string;
|
|
46
|
+
/** Notionのステータスプロパティ名。デフォルト: 'Status' */
|
|
47
|
+
status?: string;
|
|
48
|
+
/** Notionの公開日プロパティ名。デフォルト: 'CreatedAt' */
|
|
49
|
+
date?: string;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { StorageBinary as a, CachedItemList as i, CMSSchemaProperties as n, CachedItem as r, BaseContentItem as t };
|
|
53
|
+
//# sourceMappingURL=content-BrwEY2_p.d.mts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
//#region src/errors.d.ts
|
|
1
2
|
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
|
/**
|
|
3
4
|
* CMS エラーコード。
|
|
@@ -6,25 +7,26 @@ type BuiltInCMSErrorCode = "core/config_invalid" | "core/schema_invalid" | "sour
|
|
|
6
7
|
*/
|
|
7
8
|
type CMSErrorCode = BuiltInCMSErrorCode | (string & {});
|
|
8
9
|
interface CMSErrorContext {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
operation: string;
|
|
11
|
+
slug?: string;
|
|
12
|
+
dataSourceId?: string;
|
|
13
|
+
pageId?: string;
|
|
14
|
+
[key: string]: string | number | boolean | null | undefined;
|
|
14
15
|
}
|
|
15
16
|
declare class CMSError extends Error {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
readonly code: CMSErrorCode;
|
|
18
|
+
readonly cause?: unknown;
|
|
19
|
+
readonly context: CMSErrorContext;
|
|
20
|
+
constructor(params: {
|
|
21
|
+
code: CMSErrorCode;
|
|
22
|
+
message: string;
|
|
23
|
+
cause?: unknown;
|
|
24
|
+
context: CMSErrorContext;
|
|
25
|
+
});
|
|
25
26
|
}
|
|
26
27
|
declare function isCMSError(error: unknown): error is CMSError;
|
|
27
28
|
/** エラーコードが特定の名前空間に属するかを判定する(例: "source/")。 */
|
|
28
29
|
declare function isCMSErrorInNamespace(error: unknown, namespace: string): error is CMSError;
|
|
29
|
-
|
|
30
|
-
export { CMSError,
|
|
30
|
+
//#endregion
|
|
31
|
+
export { CMSError, CMSErrorCode, CMSErrorContext, isCMSError, isCMSErrorInNamespace };
|
|
32
|
+
//# sourceMappingURL=errors.d.mts.map
|
package/dist/errors.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//#region 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
|
+
/** エラーコードが特定の名前空間に属するかを判定する(例: "source/")。 */
|
|
18
|
+
function isCMSErrorInNamespace(error, namespace) {
|
|
19
|
+
return isCMSError(error) && error.code.startsWith(namespace);
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { CMSError, isCMSError, isCMSErrorInNamespace };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=errors.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"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":";AAyBA,IAAa,WAAb,cAA8B,MAAM;CACnC;CACA;CACA;CAEA,YAAY,QAKT;AACF,QAAM,OAAO,SAAS,EAAE,OAAO,OAAO,OAAO,CAAC;AAC9C,OAAK,OAAO;AACZ,OAAK,OAAO,OAAO;AACnB,OAAK,QAAQ,OAAO;AACpB,OAAK,UAAU,OAAO;;;AAIxB,SAAgB,WAAW,OAAmC;AAC7D,QAAO,iBAAiB;;;AAIzB,SAAgB,sBACf,OACA,WACoB;AACpB,QAAO,WAAW,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { r as CachedItem, t as BaseContentItem } from "./content-BrwEY2_p.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/types/hooks.d.ts
|
|
4
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
5
|
+
interface CMSHooks<T extends BaseContentItem = BaseContentItem> {
|
|
6
|
+
beforeCache?: (item: CachedItem<T>) => MaybePromise<CachedItem<T>>;
|
|
7
|
+
afterRender?: (html: string, item: T) => MaybePromise<string>;
|
|
8
|
+
onCacheHit?: (slug: string, item: CachedItem<T>) => void;
|
|
9
|
+
onCacheMiss?: (slug: string) => void;
|
|
10
|
+
onListCacheHit?: (items: T[], cachedAt: number) => void;
|
|
11
|
+
onListCacheMiss?: () => void;
|
|
12
|
+
onError?: (error: Error) => void;
|
|
13
|
+
onRenderStart?: (slug: string) => void;
|
|
14
|
+
onRenderEnd?: (slug: string, durationMs: number) => void;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/types/logger.d.ts
|
|
18
|
+
/**
|
|
19
|
+
* ログの付加情報。よく使うフィールドを型安全に渡せるようにしつつ、
|
|
20
|
+
* 任意の拡張フィールドは `[key: string]: unknown` で許容する。
|
|
21
|
+
*/
|
|
22
|
+
interface LogContext {
|
|
23
|
+
operation?: string;
|
|
24
|
+
slug?: string;
|
|
25
|
+
pageId?: string;
|
|
26
|
+
durationMs?: number;
|
|
27
|
+
attempt?: number;
|
|
28
|
+
status?: number;
|
|
29
|
+
error?: string;
|
|
30
|
+
[key: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
interface Logger {
|
|
33
|
+
debug?: (message: string, context?: LogContext) => void;
|
|
34
|
+
info?: (message: string, context?: LogContext) => void;
|
|
35
|
+
warn?: (message: string, context?: LogContext) => void;
|
|
36
|
+
error?: (message: string, context?: LogContext) => void;
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/types/plugin.d.ts
|
|
40
|
+
interface CMSPlugin<T extends BaseContentItem = BaseContentItem> {
|
|
41
|
+
name: string;
|
|
42
|
+
hooks?: CMSHooks<T>;
|
|
43
|
+
logger?: Partial<Logger>;
|
|
44
|
+
}
|
|
45
|
+
declare function definePlugin<T extends BaseContentItem>(plugin: CMSPlugin<T>): CMSPlugin<T>;
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/hooks.d.ts
|
|
48
|
+
/**
|
|
49
|
+
* プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。
|
|
50
|
+
* beforeCache / afterRender はパイプライン(前の出力が次の入力)。
|
|
51
|
+
* onCacheHit などオブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。
|
|
52
|
+
*/
|
|
53
|
+
declare function mergeHooks<T extends BaseContentItem>(plugins: CMSPlugin<T>[], directHooks?: CMSHooks<T>, logger?: Logger): CMSHooks<T>;
|
|
54
|
+
/** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */
|
|
55
|
+
declare function mergeLoggers(plugins: Array<{
|
|
56
|
+
logger?: Partial<Logger>;
|
|
57
|
+
}>, directLogger?: Logger): Logger | undefined;
|
|
58
|
+
//#endregion
|
|
59
|
+
export { Logger as a, definePlugin as i, mergeLoggers as n, CMSHooks as o, CMSPlugin as r, MaybePromise as s, mergeHooks as t };
|
|
60
|
+
//# sourceMappingURL=hooks-DCSAQkST.d.mts.map
|
package/dist/hooks.d.mts
ADDED
package/dist/hooks.mjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region src/hooks.ts
|
|
2
|
+
/**
|
|
3
|
+
* プラグイン配列とダイレクトフックを合成して単一の CMSHooks を返す。
|
|
4
|
+
* beforeCache / afterRender はパイプライン(前の出力が次の入力)。
|
|
5
|
+
* onCacheHit などオブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。
|
|
6
|
+
*/
|
|
7
|
+
function mergeHooks(plugins, directHooks, logger) {
|
|
8
|
+
const allHooks = [...plugins.map((p) => p.hooks ?? {}), ...directHooks ? [directHooks] : []];
|
|
9
|
+
if (allHooks.length === 0) return {};
|
|
10
|
+
return {
|
|
11
|
+
beforeCache: buildPipeline(allHooks, "beforeCache"),
|
|
12
|
+
afterRender: buildRenderPipeline(allHooks),
|
|
13
|
+
onCacheHit: buildObserver(allHooks, "onCacheHit", logger),
|
|
14
|
+
onCacheMiss: buildObserver(allHooks, "onCacheMiss", logger),
|
|
15
|
+
onListCacheHit: buildObserver(allHooks, "onListCacheHit", logger),
|
|
16
|
+
onListCacheMiss: buildObserver(allHooks, "onListCacheMiss", logger),
|
|
17
|
+
onError: buildObserver(allHooks, "onError", logger),
|
|
18
|
+
onRenderStart: buildObserver(allHooks, "onRenderStart", logger),
|
|
19
|
+
onRenderEnd: buildObserver(allHooks, "onRenderEnd", logger)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function buildPipeline(hooks, key) {
|
|
23
|
+
const fns = hooks.map((h) => h[key]).filter(Boolean);
|
|
24
|
+
if (fns.length === 0) return void 0;
|
|
25
|
+
return async (item) => {
|
|
26
|
+
let current = item;
|
|
27
|
+
for (const fn of fns) current = await fn(current);
|
|
28
|
+
return current;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function buildRenderPipeline(hooks) {
|
|
32
|
+
const fns = hooks.map((h) => h.afterRender).filter(Boolean);
|
|
33
|
+
if (fns.length === 0) return void 0;
|
|
34
|
+
return async (html, item) => {
|
|
35
|
+
let current = html;
|
|
36
|
+
for (const fn of fns) current = await fn(current, item);
|
|
37
|
+
return current;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function buildObserver(hooks, key, logger) {
|
|
41
|
+
const fns = hooks.map((h) => h[key]).filter(Boolean);
|
|
42
|
+
if (fns.length === 0) return void 0;
|
|
43
|
+
return ((...args) => {
|
|
44
|
+
for (const fn of fns) try {
|
|
45
|
+
fn(...args);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
logger?.error?.("観測フックで例外が発生", {
|
|
48
|
+
hook: String(key),
|
|
49
|
+
error: err instanceof Error ? err.message : String(err)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */
|
|
55
|
+
function mergeLoggers(plugins, directLogger) {
|
|
56
|
+
const loggers = [...plugins.map((p) => p.logger ?? {}), ...directLogger ? [directLogger] : []];
|
|
57
|
+
if (loggers.length === 0) return void 0;
|
|
58
|
+
const merged = {};
|
|
59
|
+
for (const level of [
|
|
60
|
+
"debug",
|
|
61
|
+
"info",
|
|
62
|
+
"warn",
|
|
63
|
+
"error"
|
|
64
|
+
]) {
|
|
65
|
+
const fns = loggers.map((l) => l[level]).filter(Boolean);
|
|
66
|
+
if (fns.length > 0) merged[level] = (message, context) => {
|
|
67
|
+
for (const fn of fns) fn(message, context);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return merged;
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { mergeHooks, mergeLoggers };
|
|
74
|
+
|
|
75
|
+
//# sourceMappingURL=hooks.mjs.map
|
|
@@ -0,0 +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 * beforeCache / afterRender はパイプライン(前の出力が次の入力)。\n * onCacheHit などオブザーバー系は全員に同じ値を渡し、例外は logger に流して握りつぶす。\n */\nexport function mergeHooks<T extends BaseContentItem>(\n\tplugins: CMSPlugin<T>[],\n\tdirectHooks?: CMSHooks<T>,\n\tlogger?: Logger,\n): CMSHooks<T> {\n\tconst allHooks: CMSHooks<T>[] = [\n\t\t...plugins.map((p) => p.hooks ?? {}),\n\t\t...(directHooks ? [directHooks] : []),\n\t];\n\n\tif (allHooks.length === 0) return {};\n\n\treturn {\n\t\tbeforeCache: buildPipeline(allHooks, \"beforeCache\"),\n\t\tafterRender: buildRenderPipeline(allHooks),\n\t\tonCacheHit: buildObserver(allHooks, \"onCacheHit\", logger),\n\t\tonCacheMiss: buildObserver(allHooks, \"onCacheMiss\", logger),\n\t\tonListCacheHit: buildObserver(allHooks, \"onListCacheHit\", logger),\n\t\tonListCacheMiss: buildObserver(allHooks, \"onListCacheMiss\", logger),\n\t\tonError: buildObserver(allHooks, \"onError\", logger),\n\t\tonRenderStart: buildObserver(allHooks, \"onRenderStart\", logger),\n\t\tonRenderEnd: buildObserver(allHooks, \"onRenderEnd\", logger),\n\t};\n}\n\nfunction buildPipeline<T extends BaseContentItem>(\n\thooks: CMSHooks<T>[],\n\tkey: \"beforeCache\",\n): CMSHooks<T>[\"beforeCache\"] {\n\tconst fns = hooks.map((h) => h[key]).filter(Boolean) as NonNullable<\n\t\tCMSHooks<T>[\"beforeCache\"]\n\t>[];\n\tif (fns.length === 0) return undefined;\n\treturn async (item) => {\n\t\tlet current = item;\n\t\tfor (const fn of fns) {\n\t\t\tcurrent = await (fn(current) as MaybePromise<typeof item>);\n\t\t}\n\t\treturn current;\n\t};\n}\n\nfunction buildRenderPipeline<T extends BaseContentItem>(\n\thooks: CMSHooks<T>[],\n): CMSHooks<T>[\"afterRender\"] {\n\tconst fns = hooks.map((h) => h.afterRender).filter(Boolean) as NonNullable<\n\t\tCMSHooks<T>[\"afterRender\"]\n\t>[];\n\tif (fns.length === 0) return undefined;\n\treturn async (html, item) => {\n\t\tlet current = html;\n\t\tfor (const fn of fns) {\n\t\t\tcurrent = await (fn(current, item) as MaybePromise<string>);\n\t\t}\n\t\treturn current;\n\t};\n}\n\nfunction buildObserver<T extends BaseContentItem, K extends keyof CMSHooks<T>>(\n\thooks: CMSHooks<T>[],\n\tkey: K,\n\tlogger?: Logger,\n): CMSHooks<T>[K] {\n\tconst fns = hooks.map((h) => h[key]).filter(Boolean);\n\tif (fns.length === 0) return undefined;\n\treturn ((...args: unknown[]) => {\n\t\tfor (const fn of fns) {\n\t\t\ttry {\n\t\t\t\t(fn as (...a: unknown[]) => void)(...args);\n\t\t\t} catch (err) {\n\t\t\t\tlogger?.error?.(\"観測フックで例外が発生\", {\n\t\t\t\t\thook: String(key),\n\t\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}) as CMSHooks<T>[K];\n}\n\n/** プラグイン配列とダイレクトロガーを合成して単一の Logger を返す。 */\nexport function mergeLoggers(\n\tplugins: Array<{ logger?: Partial<Logger> }>,\n\tdirectLogger?: Logger,\n): Logger | undefined {\n\tconst loggers: Partial<Logger>[] = [\n\t\t...plugins.map((p) => p.logger ?? {}),\n\t\t...(directLogger ? [directLogger] : []),\n\t];\n\tif (loggers.length === 0) return undefined;\n\n\tconst merged: Logger = {};\n\tfor (const level of [\"debug\", \"info\", \"warn\", \"error\"] as const) {\n\t\tconst fns = loggers.map((l) => l[level]).filter(Boolean) as NonNullable<\n\t\t\tLogger[typeof level]\n\t\t>[];\n\t\tif (fns.length > 0) {\n\t\t\tmerged[level] = (message, context) => {\n\t\t\t\tfor (const fn of fns) fn(message, context);\n\t\t\t};\n\t\t}\n\t}\n\treturn merged;\n}\n"],"mappings":";;;;;;AAUA,SAAgB,WACf,SACA,aACA,QACc;CACd,MAAM,WAA0B,CAC/B,GAAG,QAAQ,KAAK,MAAM,EAAE,SAAS,EAAE,CAAC,EACpC,GAAI,cAAc,CAAC,YAAY,GAAG,EAAE,CACpC;AAED,KAAI,SAAS,WAAW,EAAG,QAAO,EAAE;AAEpC,QAAO;EACN,aAAa,cAAc,UAAU,cAAc;EACnD,aAAa,oBAAoB,SAAS;EAC1C,YAAY,cAAc,UAAU,cAAc,OAAO;EACzD,aAAa,cAAc,UAAU,eAAe,OAAO;EAC3D,gBAAgB,cAAc,UAAU,kBAAkB,OAAO;EACjE,iBAAiB,cAAc,UAAU,mBAAmB,OAAO;EACnE,SAAS,cAAc,UAAU,WAAW,OAAO;EACnD,eAAe,cAAc,UAAU,iBAAiB,OAAO;EAC/D,aAAa,cAAc,UAAU,eAAe,OAAO;EAC3D;;AAGF,SAAS,cACR,OACA,KAC6B;CAC7B,MAAM,MAAM,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC,OAAO,QAAQ;AAGpD,KAAI,IAAI,WAAW,EAAG,QAAO,KAAA;AAC7B,QAAO,OAAO,SAAS;EACtB,IAAI,UAAU;AACd,OAAK,MAAM,MAAM,IAChB,WAAU,MAAO,GAAG,QAAQ;AAE7B,SAAO;;;AAIT,SAAS,oBACR,OAC6B;CAC7B,MAAM,MAAM,MAAM,KAAK,MAAM,EAAE,YAAY,CAAC,OAAO,QAAQ;AAG3D,KAAI,IAAI,WAAW,EAAG,QAAO,KAAA;AAC7B,QAAO,OAAO,MAAM,SAAS;EAC5B,IAAI,UAAU;AACd,OAAK,MAAM,MAAM,IAChB,WAAU,MAAO,GAAG,SAAS,KAAK;AAEnC,SAAO;;;AAIT,SAAS,cACR,OACA,KACA,QACiB;CACjB,MAAM,MAAM,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC,OAAO,QAAQ;AACpD,KAAI,IAAI,WAAW,EAAG,QAAO,KAAA;AAC7B,UAAS,GAAG,SAAoB;AAC/B,OAAK,MAAM,MAAM,IAChB,KAAI;AACF,MAAiC,GAAG,KAAK;WAClC,KAAK;AACb,WAAQ,QAAQ,eAAe;IAC9B,MAAM,OAAO,IAAI;IACjB,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACvD,CAAC;;;;;AAON,SAAgB,aACf,SACA,cACqB;CACrB,MAAM,UAA6B,CAClC,GAAG,QAAQ,KAAK,MAAM,EAAE,UAAU,EAAE,CAAC,EACrC,GAAI,eAAe,CAAC,aAAa,GAAG,EAAE,CACtC;AACD,KAAI,QAAQ,WAAW,EAAG,QAAO,KAAA;CAEjC,MAAM,SAAiB,EAAE;AACzB,MAAK,MAAM,SAAS;EAAC;EAAS;EAAQ;EAAQ;EAAQ,EAAW;EAChE,MAAM,MAAM,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,OAAO,QAAQ;AAGxD,MAAI,IAAI,SAAS,EAChB,QAAO,UAAU,SAAS,YAAY;AACrC,QAAK,MAAM,MAAM,IAAK,IAAG,SAAS,QAAQ;;;AAI7C,QAAO"}
|