@notion-headless-cms/core 0.3.8 → 0.3.10

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.
@@ -1,50 +1,2 @@
1
- import { a as CachedItemMeta, i as CachedItemList, r as CachedItemContent, s as StorageBinary, t as BaseContentItem } from "../content-DyrOwjbA.mjs";
2
- import { n as DocumentCacheAdapter, r as ImageCacheAdapter, u as InvalidateScope } from "../cache-QrXdXYMs.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 metas;
20
- private contents;
21
- private readonly maxItems;
22
- constructor(options?: MemoryDocumentCacheOptions);
23
- getList(): Promise<CachedItemList<T> | null>;
24
- setList(data: CachedItemList<T>): Promise<void>;
25
- getItemMeta(slug: string): Promise<CachedItemMeta<T> | null>;
26
- setItemMeta(slug: string, data: CachedItemMeta<T>): Promise<void>;
27
- getItemContent(slug: string): Promise<CachedItemContent | null>;
28
- setItemContent(slug: string, data: CachedItemContent): Promise<void>;
29
- invalidate(scope: InvalidateScope): Promise<void>;
30
- private enforceLimit;
31
- }
32
- /** インメモリの画像キャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
33
- declare class MemoryImageCache implements ImageCacheAdapter {
34
- readonly name = "memory-image";
35
- private store;
36
- private totalBytes;
37
- private readonly maxItems;
38
- private readonly maxSizeBytes;
39
- constructor(options?: MemoryImageCacheOptions);
40
- get(hash: string): Promise<StorageBinary | null>;
41
- set(hash: string, data: ArrayBuffer, contentType: string): Promise<void>;
42
- private enforceLimit;
43
- }
44
- /** インメモリキャッシュ(ドキュメント用)を生成する。 */
45
- declare function memoryDocumentCache<T extends BaseContentItem = BaseContentItem>(options?: MemoryDocumentCacheOptions): DocumentCacheAdapter<T>;
46
- /** インメモリキャッシュ(画像用)を生成する。 */
47
- declare function memoryImageCache(options?: MemoryImageCacheOptions): ImageCacheAdapter;
48
- //#endregion
49
- export { MemoryDocumentCache, MemoryDocumentCacheOptions, MemoryImageCache, MemoryImageCacheOptions, memoryDocumentCache, memoryImageCache };
50
- //# sourceMappingURL=memory.d.mts.map
1
+ import { i as memoryCache, n as MemoryDocumentOptions, r as MemoryImageOptions, t as MemoryCacheOptions } from "../memory-CA1uTRbr.mjs";
2
+ export { MemoryCacheOptions, MemoryDocumentOptions, MemoryImageOptions, memoryCache };
@@ -9,66 +9,74 @@ function touch(map, key) {
9
9
  map.delete(key);
10
10
  map.set(key, v);
11
11
  }
12
- /** インメモリのドキュメントキャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
13
- var MemoryDocumentCache = class {
14
- name = "memory-document";
15
- list = null;
12
+ const itemKey = (collection, slug) => `${collection}:${slug}`;
13
+ /** インメモリのドキュメントオペレーション実装。プロセス再起動でクリアされる。 */
14
+ var MemoryDocumentOps = class {
15
+ lists = /* @__PURE__ */ new Map();
16
16
  metas = /* @__PURE__ */ new Map();
17
17
  contents = /* @__PURE__ */ new Map();
18
18
  maxItems;
19
19
  constructor(options) {
20
20
  this.maxItems = options?.maxItems;
21
21
  }
22
- getList() {
23
- return Promise.resolve(this.list);
22
+ getList(collection) {
23
+ return Promise.resolve(this.lists.get(collection) ?? null);
24
24
  }
25
- setList(data) {
26
- this.list = data;
25
+ setList(collection, data) {
26
+ this.lists.set(collection, data);
27
27
  return Promise.resolve();
28
28
  }
29
- getItemMeta(slug) {
30
- const entry = this.metas.get(slug);
31
- if (entry) touch(this.metas, slug);
29
+ getMeta(collection, slug) {
30
+ const key = itemKey(collection, slug);
31
+ const entry = this.metas.get(key);
32
+ if (entry) touch(this.metas, key);
32
33
  return Promise.resolve(entry ?? null);
33
34
  }
34
- setItemMeta(slug, data) {
35
- if (this.metas.has(slug)) this.metas.delete(slug);
36
- this.metas.set(slug, data);
35
+ setMeta(collection, slug, data) {
36
+ const key = itemKey(collection, slug);
37
+ if (this.metas.has(key)) this.metas.delete(key);
38
+ this.metas.set(key, data);
37
39
  this.enforceLimit();
38
40
  return Promise.resolve();
39
41
  }
40
- getItemContent(slug) {
41
- const entry = this.contents.get(slug);
42
- if (entry) touch(this.contents, slug);
42
+ getContent(collection, slug) {
43
+ const key = itemKey(collection, slug);
44
+ const entry = this.contents.get(key);
45
+ if (entry) touch(this.contents, key);
43
46
  return Promise.resolve(entry ?? null);
44
47
  }
45
- setItemContent(slug, data) {
46
- if (this.contents.has(slug)) this.contents.delete(slug);
47
- this.contents.set(slug, data);
48
+ setContent(collection, slug, data) {
49
+ const key = itemKey(collection, slug);
50
+ if (this.contents.has(key)) this.contents.delete(key);
51
+ this.contents.set(key, data);
48
52
  this.enforceLimit();
49
53
  return Promise.resolve();
50
54
  }
51
- async invalidate(scope) {
55
+ invalidate(scope) {
52
56
  if (scope === "all") {
53
- this.list = null;
57
+ this.lists.clear();
54
58
  this.metas.clear();
55
59
  this.contents.clear();
56
- return;
60
+ return Promise.resolve();
57
61
  }
58
62
  const kind = scope.kind ?? "all";
59
- if (kind === "all" || kind === "meta") this.list = null;
63
+ const collection = scope.collection;
60
64
  if ("slug" in scope) {
61
- if (kind === "all" || kind === "meta") this.metas.delete(scope.slug);
62
- if (kind === "all" || kind === "content") this.contents.delete(scope.slug);
63
- } else {
64
- const prefix = `${scope.collection}:`;
65
- if (kind === "all" || kind === "meta") {
66
- for (const key of [...this.metas.keys()]) if (key.startsWith(prefix)) this.metas.delete(key);
67
- }
68
- if (kind === "all" || kind === "content") {
69
- for (const key of [...this.contents.keys()]) if (key.startsWith(prefix)) this.contents.delete(key);
70
- }
65
+ const key = itemKey(collection, scope.slug);
66
+ if (kind === "all" || kind === "meta") this.metas.delete(key);
67
+ if (kind === "all" || kind === "content") this.contents.delete(key);
68
+ return Promise.resolve();
71
69
  }
70
+ if (kind === "all" || kind === "meta") {
71
+ this.lists.delete(collection);
72
+ const prefix = `${collection}:`;
73
+ for (const key of [...this.metas.keys()]) if (key.startsWith(prefix)) this.metas.delete(key);
74
+ }
75
+ if (kind === "all" || kind === "content") {
76
+ const prefix = `${collection}:`;
77
+ for (const key of [...this.contents.keys()]) if (key.startsWith(prefix)) this.contents.delete(key);
78
+ }
79
+ return Promise.resolve();
72
80
  }
73
81
  enforceLimit() {
74
82
  if (this.maxItems === void 0) return;
@@ -84,9 +92,8 @@ var MemoryDocumentCache = class {
84
92
  }
85
93
  }
86
94
  };
87
- /** インメモリの画像キャッシュ実装。プロセス再起動でクリアされる。ローカル開発向け。 */
88
- var MemoryImageCache = class {
89
- name = "memory-image";
95
+ /** インメモリの画像オペレーション実装。 */
96
+ var MemoryImageOps = class {
90
97
  store = /* @__PURE__ */ new Map();
91
98
  totalBytes = 0;
92
99
  maxItems;
@@ -124,15 +131,22 @@ var MemoryImageCache = class {
124
131
  }
125
132
  }
126
133
  };
127
- /** インメモリキャッシュ(ドキュメント用)を生成する。 */
128
- function memoryDocumentCache(options) {
129
- return new MemoryDocumentCache(options);
130
- }
131
- /** インメモリキャッシュ(画像用)を生成する。 */
132
- function memoryImageCache(options) {
133
- return new MemoryImageCache(options);
134
+ /**
135
+ * インメモリのキャッシュアダプタ。document + image 両方を担当する。
136
+ * プロセス再起動でクリアされるため、ローカル開発・SSG ビルド・テスト用途。
137
+ *
138
+ * @example
139
+ * cache: memoryCache({ ttlMs: 5 * 60_000, maxItems: 1000 })
140
+ */
141
+ function memoryCache(options) {
142
+ return {
143
+ name: "memory",
144
+ handles: ["document", "image"],
145
+ doc: new MemoryDocumentOps(options),
146
+ img: new MemoryImageOps(options)
147
+ };
134
148
  }
135
149
  //#endregion
136
- export { MemoryDocumentCache, MemoryImageCache, memoryDocumentCache, memoryImageCache };
150
+ export { memoryCache };
137
151
 
138
152
  //# sourceMappingURL=memory.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory.mjs","names":[],"sources":["../../src/cache/memory.ts"],"sourcesContent":["import type {\n\tBaseContentItem,\n\tCachedItemContent,\n\tCachedItemList,\n\tCachedItemMeta,\n\tDocumentCacheAdapter,\n\tImageCacheAdapter,\n\tInvalidateScope,\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 metas = new Map<string, CachedItemMeta<T>>();\n\tprivate contents = new Map<string, CachedItemContent>();\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\tgetItemMeta(slug: string): Promise<CachedItemMeta<T> | null> {\n\t\tconst entry = this.metas.get(slug);\n\t\tif (entry) touch(this.metas, slug);\n\t\treturn Promise.resolve(entry ?? null);\n\t}\n\n\tsetItemMeta(slug: string, data: CachedItemMeta<T>): Promise<void> {\n\t\tif (this.metas.has(slug)) this.metas.delete(slug);\n\t\tthis.metas.set(slug, data);\n\t\tthis.enforceLimit();\n\t\treturn Promise.resolve();\n\t}\n\n\tgetItemContent(slug: string): Promise<CachedItemContent | null> {\n\t\tconst entry = this.contents.get(slug);\n\t\tif (entry) touch(this.contents, slug);\n\t\treturn Promise.resolve(entry ?? null);\n\t}\n\n\tsetItemContent(slug: string, data: CachedItemContent): Promise<void> {\n\t\tif (this.contents.has(slug)) this.contents.delete(slug);\n\t\tthis.contents.set(slug, data);\n\t\tthis.enforceLimit();\n\t\treturn Promise.resolve();\n\t}\n\n\tasync invalidate(scope: InvalidateScope): Promise<void> {\n\t\tif (scope === \"all\") {\n\t\t\tthis.list = null;\n\t\t\tthis.metas.clear();\n\t\t\tthis.contents.clear();\n\t\t\treturn;\n\t\t}\n\t\tconst kind = scope.kind ?? \"all\";\n\t\tif (kind === \"all\" || kind === \"meta\") {\n\t\t\tthis.list = null;\n\t\t}\n\t\tif (\"slug\" in scope) {\n\t\t\tif (kind === \"all\" || kind === \"meta\") this.metas.delete(scope.slug);\n\t\t\tif (kind === \"all\" || kind === \"content\")\n\t\t\t\tthis.contents.delete(scope.slug);\n\t\t} else {\n\t\t\t// scopeDocumentCache 経由でキーは `{collection}:{slug}` 形式になる\n\t\t\tconst prefix = `${scope.collection}:`;\n\t\t\tif (kind === \"all\" || kind === \"meta\") {\n\t\t\t\tfor (const key of [...this.metas.keys()]) {\n\t\t\t\t\tif (key.startsWith(prefix)) this.metas.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (kind === \"all\" || kind === \"content\") {\n\t\t\t\tfor (const key of [...this.contents.keys()]) {\n\t\t\t\t\tif (key.startsWith(prefix)) this.contents.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate enforceLimit(): void {\n\t\tif (this.maxItems === undefined) return;\n\t\twhile (this.metas.size > this.maxItems) {\n\t\t\tconst firstKey = this.metas.keys().next().value;\n\t\t\tif (firstKey === undefined) break;\n\t\t\tthis.metas.delete(firstKey);\n\t\t}\n\t\twhile (this.contents.size > this.maxItems) {\n\t\t\tconst firstKey = this.contents.keys().next().value;\n\t\t\tif (firstKey === undefined) break;\n\t\t\tthis.contents.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"],"mappings":"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"}
1
+ {"version":3,"file":"memory.mjs","names":[],"sources":["../../src/cache/memory.ts"],"sourcesContent":["import type {\n\tBaseContentItem,\n\tCacheAdapter,\n\tCachedItemContent,\n\tCachedItemList,\n\tCachedItemMeta,\n\tDocumentCacheOps,\n\tImageCacheOps,\n\tInvalidateScope,\n\tStorageBinary,\n} from \"../types/index\";\n\nexport interface MemoryDocumentOptions {\n\t/** アイテム保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */\n\tmaxItems?: number;\n}\n\nexport interface MemoryImageOptions {\n\t/** エントリ保持上限。未指定時は上限なし。超過時は LRU で古いものから削除。 */\n\tmaxItems?: number;\n\t/** 合計保持サイズ上限(バイト)。未指定時は上限なし。超過時は LRU で古いものから削除。 */\n\tmaxSizeBytes?: number;\n}\n\nexport interface MemoryCacheOptions\n\textends MemoryDocumentOptions,\n\t\tMemoryImageOptions {}\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\nconst itemKey = (collection: string, slug: string): string =>\n\t`${collection}:${slug}`;\n\n/** インメモリのドキュメントオペレーション実装。プロセス再起動でクリアされる。 */\nclass MemoryDocumentOps implements DocumentCacheOps {\n\t// biome-ignore lint/suspicious/noExplicitAny: 複数コレクション分の T を一括保持\n\tprivate lists = new Map<string, CachedItemList<any>>();\n\t// biome-ignore lint/suspicious/noExplicitAny: 同上\n\tprivate metas = new Map<string, CachedItemMeta<any>>();\n\tprivate contents = new Map<string, CachedItemContent>();\n\tprivate readonly maxItems: number | undefined;\n\n\tconstructor(options?: MemoryDocumentOptions) {\n\t\tthis.maxItems = options?.maxItems;\n\t}\n\n\tgetList<T extends BaseContentItem>(\n\t\tcollection: string,\n\t): Promise<CachedItemList<T> | null> {\n\t\treturn Promise.resolve(\n\t\t\t(this.lists.get(collection) as CachedItemList<T> | undefined) ?? null,\n\t\t);\n\t}\n\n\tsetList<T extends BaseContentItem>(\n\t\tcollection: string,\n\t\tdata: CachedItemList<T>,\n\t): Promise<void> {\n\t\tthis.lists.set(collection, data);\n\t\treturn Promise.resolve();\n\t}\n\n\tgetMeta<T extends BaseContentItem>(\n\t\tcollection: string,\n\t\tslug: string,\n\t): Promise<CachedItemMeta<T> | null> {\n\t\tconst key = itemKey(collection, slug);\n\t\tconst entry = this.metas.get(key) as CachedItemMeta<T> | undefined;\n\t\tif (entry) touch(this.metas, key);\n\t\treturn Promise.resolve(entry ?? null);\n\t}\n\n\tsetMeta<T extends BaseContentItem>(\n\t\tcollection: string,\n\t\tslug: string,\n\t\tdata: CachedItemMeta<T>,\n\t): Promise<void> {\n\t\tconst key = itemKey(collection, slug);\n\t\tif (this.metas.has(key)) this.metas.delete(key);\n\t\tthis.metas.set(key, data);\n\t\tthis.enforceLimit();\n\t\treturn Promise.resolve();\n\t}\n\n\tgetContent(\n\t\tcollection: string,\n\t\tslug: string,\n\t): Promise<CachedItemContent | null> {\n\t\tconst key = itemKey(collection, slug);\n\t\tconst entry = this.contents.get(key);\n\t\tif (entry) touch(this.contents, key);\n\t\treturn Promise.resolve(entry ?? null);\n\t}\n\n\tsetContent(\n\t\tcollection: string,\n\t\tslug: string,\n\t\tdata: CachedItemContent,\n\t): Promise<void> {\n\t\tconst key = itemKey(collection, slug);\n\t\tif (this.contents.has(key)) this.contents.delete(key);\n\t\tthis.contents.set(key, data);\n\t\tthis.enforceLimit();\n\t\treturn Promise.resolve();\n\t}\n\n\tinvalidate(scope: InvalidateScope): Promise<void> {\n\t\tif (scope === \"all\") {\n\t\t\tthis.lists.clear();\n\t\t\tthis.metas.clear();\n\t\t\tthis.contents.clear();\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tconst kind = scope.kind ?? \"all\";\n\t\tconst collection = scope.collection;\n\t\tif (\"slug\" in scope) {\n\t\t\tconst key = itemKey(collection, scope.slug);\n\t\t\tif (kind === \"all\" || kind === \"meta\") this.metas.delete(key);\n\t\t\tif (kind === \"all\" || kind === \"content\") this.contents.delete(key);\n\t\t\t// 単一スラッグ無効化ではリストは触らない(リスト全体の整合は別管理)\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\t// コレクション全体\n\t\tif (kind === \"all\" || kind === \"meta\") {\n\t\t\tthis.lists.delete(collection);\n\t\t\tconst prefix = `${collection}:`;\n\t\t\tfor (const key of [...this.metas.keys()]) {\n\t\t\t\tif (key.startsWith(prefix)) this.metas.delete(key);\n\t\t\t}\n\t\t}\n\t\tif (kind === \"all\" || kind === \"content\") {\n\t\t\tconst prefix = `${collection}:`;\n\t\t\tfor (const key of [...this.contents.keys()]) {\n\t\t\t\tif (key.startsWith(prefix)) this.contents.delete(key);\n\t\t\t}\n\t\t}\n\t\treturn Promise.resolve();\n\t}\n\n\tprivate enforceLimit(): void {\n\t\tif (this.maxItems === undefined) return;\n\t\twhile (this.metas.size > this.maxItems) {\n\t\t\tconst firstKey = this.metas.keys().next().value;\n\t\t\tif (firstKey === undefined) break;\n\t\t\tthis.metas.delete(firstKey);\n\t\t}\n\t\twhile (this.contents.size > this.maxItems) {\n\t\t\tconst firstKey = this.contents.keys().next().value;\n\t\t\tif (firstKey === undefined) break;\n\t\t\tthis.contents.delete(firstKey);\n\t\t}\n\t}\n}\n\n/** インメモリの画像オペレーション実装。 */\nclass MemoryImageOps implements ImageCacheOps {\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?: MemoryImageOptions) {\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/**\n * インメモリのキャッシュアダプタ。document + image 両方を担当する。\n * プロセス再起動でクリアされるため、ローカル開発・SSG ビルド・テスト用途。\n *\n * @example\n * cache: memoryCache({ ttlMs: 5 * 60_000, maxItems: 1000 })\n */\nexport function memoryCache(options?: MemoryCacheOptions): CacheAdapter {\n\treturn {\n\t\tname: \"memory\",\n\t\thandles: [\"document\", \"image\"] as const,\n\t\tdoc: new MemoryDocumentOps(options),\n\t\timg: new MemoryImageOps(options),\n\t};\n}\n"],"mappings":"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"}
@@ -94,10 +94,10 @@ interface BaseContentItem {
94
94
  title?: string | null;
95
95
  /** 最終更新タイムスタンプ(変更検知に必須)。 */
96
96
  updatedAt: string;
97
- /** コンテンツのステータス。ステータスのない DB では省略可能。 */
98
- status?: string;
99
- /** 公開日時。日付プロパティのない DB では省略可能。 */
100
- publishedAt?: string;
97
+ /** コンテンツのステータス。ステータスのない DB では省略可能。Notion の select 型は null を返す場合がある。 */
98
+ status?: string | null;
99
+ /** 公開日時。日付プロパティのない DB では省略可能。Notion の date 型は null を返す場合がある。 */
100
+ publishedAt?: string | null;
101
101
  }
102
102
  /**
103
103
  * メタデータのみの軽量キャッシュエントリ。
@@ -122,16 +122,6 @@ interface CachedItemContent {
122
122
  notionUpdatedAt: string;
123
123
  cachedAt: number;
124
124
  }
125
- /**
126
- * 本文クライアント送信用 DTO(cachedAt を除いた `CachedItemContent`)。
127
- * `useSWR` の cache に格納できるよう関数を含まない pure JSON。
128
- */
129
- interface ItemContentPayload {
130
- html: string;
131
- markdown: string;
132
- blocks: ContentBlock[];
133
- notionUpdatedAt: string;
134
- }
135
125
  /** ストレージにキャッシュされたコンテンツ一覧。 */
136
126
  interface CachedItemList<T extends BaseContentItem = BaseContentItem> {
137
127
  items: T[];
@@ -152,5 +142,5 @@ interface CMSSchemaProperties {
152
142
  date?: string;
153
143
  }
154
144
  //#endregion
155
- export { CachedItemMeta as a, ContentBlock as c, InlineNode as d, CachedItemList as i, ContentResult as l, CMSSchemaProperties as n, ItemContentPayload as o, CachedItemContent as r, StorageBinary as s, BaseContentItem as t, ImageRef as u };
156
- //# sourceMappingURL=content-DyrOwjbA.d.mts.map
145
+ export { CachedItemMeta as a, ContentResult as c, CachedItemList as i, ImageRef as l, CMSSchemaProperties as n, StorageBinary as o, CachedItemContent as r, ContentBlock as s, BaseContentItem as t, InlineNode as u };
146
+ //# sourceMappingURL=content-Bffid8da.d.mts.map
@@ -1,4 +1,4 @@
1
- import { a as CachedItemMeta, i as CachedItemList, r as CachedItemContent, t as BaseContentItem } from "./content-DyrOwjbA.mjs";
1
+ import { a as CachedItemMeta, i as CachedItemList, r as CachedItemContent, t as BaseContentItem } from "./content-Bffid8da.mjs";
2
2
 
3
3
  //#region src/types/hooks.d.ts
4
4
  type MaybePromise<T> = T | Promise<T>;
@@ -75,4 +75,4 @@ declare function mergeLoggers(plugins: Array<{
75
75
  }>, directLogger?: Logger): Logger | undefined;
76
76
  //#endregion
77
77
  export { Logger as a, definePlugin as i, mergeLoggers as n, CMSHooks as o, CMSPlugin as r, MaybePromise as s, mergeHooks as t };
78
- //# sourceMappingURL=hooks-CPRRo9IN.d.mts.map
78
+ //# sourceMappingURL=hooks-CqqVxrYg.d.mts.map
package/dist/hooks.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as mergeLoggers, t as mergeHooks } from "./hooks-CPRRo9IN.mjs";
1
+ import { n as mergeLoggers, t as mergeHooks } from "./hooks-CqqVxrYg.mjs";
2
2
  export { mergeHooks, mergeLoggers };