@notion-headless-cms/core 0.3.19 → 0.3.20
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 +3 -3
- package/dist/html.d.mts +23 -0
- package/dist/html.mjs +19 -0
- package/dist/html.mjs.map +1 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -30,7 +30,6 @@ const cms = createClient({
|
|
|
30
30
|
}),
|
|
31
31
|
},
|
|
32
32
|
cache: [memoryCache()],
|
|
33
|
-
swr: { ttlMs: 5 * 60_000 },
|
|
34
33
|
});
|
|
35
34
|
|
|
36
35
|
const posts = await cms.posts.list();
|
|
@@ -47,7 +46,7 @@ if (post) console.log(await post.render());
|
|
|
47
46
|
| `sources` | データソースアダプターのマップ(`{ notion: notionSource(...) }` 等)。複数ソースの `collections` は自動マージされる |
|
|
48
47
|
| `collections` | 直接 `CollectionDef` を渡す低レベル API(通常は `sources` を使う) |
|
|
49
48
|
| `cache` | `readonly CacheAdapter[]` — `memoryCache()` / `cloudflareCache(env)` 等を配列で指定 |
|
|
50
|
-
| `swr` | `{ ttlMs?: number }` — SWR
|
|
49
|
+
| `swr` | `{ ttlMs?: number }` — SWR の TTL。未指定だとキャッシュは期限なしで永続し、Notion の `lastEditedTime` 差分があれば bg で差し替え。指定するとブロッキング再取得が走る |
|
|
51
50
|
| `renderer` | `RendererFn` — 未指定なら `@notion-headless-cms/renderer` を動的ロード |
|
|
52
51
|
| `imageProxyBase` | 画像プロキシのベース URL(デフォルト `/api/images`) |
|
|
53
52
|
| `waitUntil` | Cloudflare Workers の `ctx.waitUntil` 相当 |
|
|
@@ -103,7 +102,7 @@ CLI 生成物の各アイテム型は `BaseContentItem` を拡張する:
|
|
|
103
102
|
|
|
104
103
|
- `memoryCache({ maxItems? })` — インプロセス LRU
|
|
105
104
|
- `noopDocOps` / `noopImgOps` — キャッシュ無効化用
|
|
106
|
-
- 別パッケージ: `@notion-headless-cms/cache/cloudflare` の `
|
|
105
|
+
- 別パッケージ: `@notion-headless-cms/cache/cloudflare` の `cloudflarePreset({ env, ctx })` / `cloudflareCache(...)` / `r2Cache()` / `kvCache()`、`@notion-headless-cms/cache/next` の `nextCache()`
|
|
107
106
|
|
|
108
107
|
### エラー
|
|
109
108
|
|
|
@@ -124,6 +123,7 @@ import { memoryCache } from "@notion-headless-cms/core/cache/memory";
|
|
|
124
123
|
| `@notion-headless-cms/core/hooks` | `mergeHooks` / `mergeLoggers` |
|
|
125
124
|
| `@notion-headless-cms/core/cache/memory` | `memoryCache` |
|
|
126
125
|
| `@notion-headless-cms/core/cache/noop` | `noopDocOps` / `noopImgOps` |
|
|
126
|
+
| `@notion-headless-cms/core/html` | `notionRevalidatorScript` (Astro / Hono / Express など素 HTML 向け) |
|
|
127
127
|
|
|
128
128
|
## ランタイム別レシピ
|
|
129
129
|
|
package/dist/html.d.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/html.d.ts
|
|
2
|
+
interface NotionRevalidatorScriptOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 再検証のトリガー。既定値: "visibility"
|
|
5
|
+
* - "visibility": タブ可視化 (`visibilitychange` で hidden→visible) の度に reload
|
|
6
|
+
* - "focus": ウィンドウ focus の度に reload (visibility より発火が頻繁)
|
|
7
|
+
*/
|
|
8
|
+
on?: "visibility" | "focus";
|
|
9
|
+
/**
|
|
10
|
+
* `<script nonce="...">` を出力したい場合 (CSP 対応)。
|
|
11
|
+
* 英数字・`-` / `_` / `+` / `/` / `=` のみ許可。属性値ブレイクアウトを防ぐため
|
|
12
|
+
* 不正な文字が含まれていれば throw する。
|
|
13
|
+
*/
|
|
14
|
+
nonce?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* React を使わないページに埋め込むための `<script>...</script>` 文字列を返す。
|
|
18
|
+
* 返り値は外部入力を埋め込まない(nonce は厳格に検証)safe な内容。
|
|
19
|
+
*/
|
|
20
|
+
declare function notionRevalidatorScript(opts?: NotionRevalidatorScriptOptions): string;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { NotionRevalidatorScriptOptions, notionRevalidatorScript };
|
|
23
|
+
//# sourceMappingURL=html.d.mts.map
|
package/dist/html.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/html.ts
|
|
2
|
+
const NONCE_PATTERN = /^[A-Za-z0-9+/=_-]+$/;
|
|
3
|
+
/**
|
|
4
|
+
* React を使わないページに埋め込むための `<script>...<\/script>` 文字列を返す。
|
|
5
|
+
* 返り値は外部入力を埋め込まない(nonce は厳格に検証)safe な内容。
|
|
6
|
+
*/
|
|
7
|
+
function notionRevalidatorScript(opts = {}) {
|
|
8
|
+
const body = (opts.on ?? "visibility") === "focus" ? "let l=false;addEventListener(\"focus\",()=>{if(l)location.reload();l=true});" : "document.addEventListener(\"visibilitychange\",()=>{if(document.visibilityState===\"visible\")location.reload()});";
|
|
9
|
+
let nonceAttr = "";
|
|
10
|
+
if (opts.nonce !== void 0) {
|
|
11
|
+
if (!NONCE_PATTERN.test(opts.nonce)) throw new Error("notionRevalidatorScript: nonce に不正な文字が含まれています。base64 / base64url 由来の英数字のみ受け付けます。");
|
|
12
|
+
nonceAttr = ` nonce="${opts.nonce}"`;
|
|
13
|
+
}
|
|
14
|
+
return `<script${nonceAttr}>(()=>{${body}})();<\/script>`;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { notionRevalidatorScript };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=html.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.mjs","names":[],"sources":["../src/html.ts"],"sourcesContent":["// React を使わないテンプレート (Astro / Hono / Express など) で SWR 体験を\n// 成立させるための、ゼロ依存の小さな <script> 文字列ジェネレータ。\n//\n// 使い方 (Astro):\n// import { notionRevalidatorScript } from \"@notion-headless-cms/core/html\";\n// <Fragment set:html={notionRevalidatorScript()} />\n//\n// 使い方 (Hono):\n// import { raw, html as h } from \"hono/html\";\n// c.html(h`...${raw(notionRevalidatorScript())}`);\n//\n// 仕組み: タブ可視化 (visibilitychange で hidden→visible) を検知して\n// `location.reload()` で同じ URL を再リクエストする。サーバ側は\n// `cloudflarePreset` 等で `waitUntil` が配線されていれば、前回訪問時に\n// SWR bg が KV を最新化済み → 再取得で新内容が返る。クエリ無し・別 API fetch 無し。\n\nexport interface NotionRevalidatorScriptOptions {\n /**\n * 再検証のトリガー。既定値: \"visibility\"\n * - \"visibility\": タブ可視化 (`visibilitychange` で hidden→visible) の度に reload\n * - \"focus\": ウィンドウ focus の度に reload (visibility より発火が頻繁)\n */\n on?: \"visibility\" | \"focus\";\n /**\n * `<script nonce=\"...\">` を出力したい場合 (CSP 対応)。\n * 英数字・`-` / `_` / `+` / `/` / `=` のみ許可。属性値ブレイクアウトを防ぐため\n * 不正な文字が含まれていれば throw する。\n */\n nonce?: string;\n}\n\n// CSP nonce は本来 base64 / base64url 由来のランダム文字列。属性値の\n// クォート・タグブレイクアウトを未然に防ぐため、最小限の許可セットで検証する。\nconst NONCE_PATTERN = /^[A-Za-z0-9+/=_-]+$/;\n\n/**\n * React を使わないページに埋め込むための `<script>...</script>` 文字列を返す。\n * 返り値は外部入力を埋め込まない(nonce は厳格に検証)safe な内容。\n */\nexport function notionRevalidatorScript(\n opts: NotionRevalidatorScriptOptions = {},\n): string {\n const trigger = opts.on ?? \"visibility\";\n const body =\n trigger === \"focus\"\n ? // 初回ロード時の focus は無視するため、loaded フラグで初回をスキップ。\n 'let l=false;addEventListener(\"focus\",()=>{if(l)location.reload();l=true});'\n : 'document.addEventListener(\"visibilitychange\",()=>{if(document.visibilityState===\"visible\")location.reload()});';\n let nonceAttr = \"\";\n if (opts.nonce !== undefined) {\n if (!NONCE_PATTERN.test(opts.nonce)) {\n throw new Error(\n \"notionRevalidatorScript: nonce に不正な文字が含まれています。base64 / base64url 由来の英数字のみ受け付けます。\",\n );\n }\n nonceAttr = ` nonce=\"${opts.nonce}\"`;\n }\n return `<script${nonceAttr}>(()=>{${body}})();</script>`;\n}\n"],"mappings":";AAiCA,MAAM,gBAAgB;;;;;AAMtB,SAAgB,wBACd,OAAuC,EAAE,EACjC;CAER,MAAM,QADU,KAAK,MAAM,kBAEb,UAER,iFACA;CACN,IAAI,YAAY;AAChB,KAAI,KAAK,UAAU,KAAA,GAAW;AAC5B,MAAI,CAAC,cAAc,KAAK,KAAK,MAAM,CACjC,OAAM,IAAI,MACR,mFACD;AAEH,cAAY,WAAW,KAAK,MAAM;;AAEpC,QAAO,UAAU,UAAU,SAAS,KAAK"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notion-headless-cms/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.20",
|
|
4
4
|
"description": "Core CMS engine for notion-headless-cms — fetch, transform, cache with stale-while-revalidate strategy",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"notion",
|
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
"./cache/memory": {
|
|
39
39
|
"types": "./dist/cache/memory.d.mts",
|
|
40
40
|
"import": "./dist/cache/memory.mjs"
|
|
41
|
+
},
|
|
42
|
+
"./html": {
|
|
43
|
+
"types": "./dist/html.d.mts",
|
|
44
|
+
"import": "./dist/html.mjs"
|
|
41
45
|
}
|
|
42
46
|
},
|
|
43
47
|
"files": [
|
|
@@ -60,7 +64,7 @@
|
|
|
60
64
|
},
|
|
61
65
|
"devDependencies": {},
|
|
62
66
|
"scripts": {
|
|
63
|
-
"build": "tsdown src/index.ts src/errors.ts src/hooks.ts src/cache/memory.ts --format esm --dts --sourcemap --out-dir dist",
|
|
67
|
+
"build": "tsdown src/index.ts src/errors.ts src/hooks.ts src/cache/memory.ts src/html.ts --format esm --dts --sourcemap --out-dir dist",
|
|
64
68
|
"typecheck": "tsc --noEmit",
|
|
65
69
|
"test": "vitest run",
|
|
66
70
|
"test:coverage": "vitest run --coverage --coverage.reporter=lcov --coverage.reporter=text",
|