@datum-cloud/strapi-revalidate 0.1.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/.env.example +5 -0
- package/LICENSE +121 -0
- package/README.md +227 -0
- package/dist/cache/drivers/file.d.ts +37 -0
- package/dist/cache/drivers/file.d.ts.map +1 -0
- package/dist/cache/drivers/file.js +151 -0
- package/dist/cache/drivers/file.js.map +1 -0
- package/dist/cache/drivers/memory.d.ts +20 -0
- package/dist/cache/drivers/memory.d.ts.map +1 -0
- package/dist/cache/drivers/memory.js +76 -0
- package/dist/cache/drivers/memory.js.map +1 -0
- package/dist/cache/drivers/redis.d.ts +25 -0
- package/dist/cache/drivers/redis.d.ts.map +1 -0
- package/dist/cache/drivers/redis.js +36 -0
- package/dist/cache/drivers/redis.js.map +1 -0
- package/dist/cache/index.d.ts +28 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +54 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/manager.d.ts +55 -0
- package/dist/cache/manager.d.ts.map +1 -0
- package/dist/cache/manager.js +73 -0
- package/dist/cache/manager.js.map +1 -0
- package/dist/cache/types.d.ts +33 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +9 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/client/graphql.d.ts +46 -0
- package/dist/client/graphql.d.ts.map +1 -0
- package/dist/client/graphql.js +97 -0
- package/dist/client/graphql.js.map +1 -0
- package/dist/client/index.d.ts +28 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +38 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/rest.d.ts +23 -0
- package/dist/client/rest.d.ts.map +1 -0
- package/dist/client/rest.js +25 -0
- package/dist/client/rest.js.map +1 -0
- package/dist/content/articles.d.ts +36 -0
- package/dist/content/articles.d.ts.map +1 -0
- package/dist/content/articles.js +157 -0
- package/dist/content/articles.js.map +1 -0
- package/dist/content/authors.d.ts +28 -0
- package/dist/content/authors.d.ts.map +1 -0
- package/dist/content/authors.js +115 -0
- package/dist/content/authors.js.map +1 -0
- package/dist/content/index.d.ts +11 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +10 -0
- package/dist/content/index.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/types/config.d.ts +108 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +49 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/strapi.d.ts +103 -0
- package/dist/types/strapi.d.ts.map +1 -0
- package/dist/types/strapi.js +11 -0
- package/dist/types/strapi.js.map +1 -0
- package/dist/webhook/handler.d.ts +38 -0
- package/dist/webhook/handler.d.ts.map +1 -0
- package/dist/webhook/handler.js +156 -0
- package/dist/webhook/handler.js.map +1 -0
- package/dist/webhook/index.d.ts +9 -0
- package/dist/webhook/index.d.ts.map +1 -0
- package/dist/webhook/index.js +7 -0
- package/dist/webhook/index.js.map +1 -0
- package/dist/webhook/tags.d.ts +22 -0
- package/dist/webhook/tags.d.ts.map +1 -0
- package/dist/webhook/tags.js +39 -0
- package/dist/webhook/tags.js.map +1 -0
- package/dist/webhook/types.d.ts +60 -0
- package/dist/webhook/types.d.ts.map +1 -0
- package/dist/webhook/types.js +6 -0
- package/dist/webhook/types.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Article fetchers.
|
|
3
|
+
*
|
|
4
|
+
* Refactored from datum.net's `articles.ts`: same GraphQL queries and same
|
|
5
|
+
* primary-then-fallback read pattern, but the client and cache are injected
|
|
6
|
+
* rather than module-level singletons. Datum-specific transforms (block
|
|
7
|
+
* stripping, top-3 cover preservation, reading-time calculation) are
|
|
8
|
+
* intentionally not ported — those belong in application code.
|
|
9
|
+
*/
|
|
10
|
+
import type { CacheManager } from '../cache/manager.js';
|
|
11
|
+
import type { StrapiClient } from '../client/index.js';
|
|
12
|
+
import type { StrapiArticle } from '../types/strapi.js';
|
|
13
|
+
/** GraphQL query: every published article, newest first. */
|
|
14
|
+
export declare const ARTICLES_QUERY = "\n query GetArticles {\n articles(pagination: { limit: 100 }, sort: [\"originalPublishedAt:desc\"]) {\n documentId\n title\n slug\n description\n originalPublishedAt\n blocks {\n __typename\n ... on ComponentSharedRichText {\n id\n body\n }\n }\n cover {\n url\n alternativeText\n width\n height\n formats\n }\n author {\n documentId\n slug\n name\n isTeam\n avatar {\n url\n alternativeText\n }\n }\n category {\n name\n slug\n }\n }\n }\n";
|
|
15
|
+
/** GraphQL query: a single article by slug, including SEO and quote blocks. */
|
|
16
|
+
export declare const ARTICLE_BY_SLUG_QUERY = "\n query GetArticleBySlug($slug: String!) {\n articles(filters: { slug: { eq: $slug } }) {\n documentId\n title\n slug\n description\n originalPublishedAt\n blocks {\n __typename\n ... on ComponentSharedQuote {\n body\n title\n }\n ... on ComponentSharedRichText {\n id\n body\n }\n }\n cover {\n url\n alternativeText\n width\n height\n formats\n }\n author {\n documentId\n slug\n name\n isTeam\n avatar {\n url\n alternativeText\n }\n }\n category {\n name\n slug\n }\n seo {\n metaTitle\n metaDescription\n ogTitle\n ogDescription\n shareImage {\n url\n }\n }\n }\n }\n";
|
|
17
|
+
/** Dependencies threaded into every content fetcher. */
|
|
18
|
+
export interface ContentDeps {
|
|
19
|
+
client: StrapiClient;
|
|
20
|
+
cache: CacheManager;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fetch every article from Strapi. Reads from cache first; on Strapi failure,
|
|
24
|
+
* serves stale data from the persistent fallback cache instead of throwing.
|
|
25
|
+
*
|
|
26
|
+
* Cache key: `strapi-articles`. Tags: `["articles"]`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function fetchArticles({ client, cache }: ContentDeps): Promise<StrapiArticle[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch a single article by slug. Cached per slug; falls back to stale
|
|
31
|
+
* data when Strapi is unreachable.
|
|
32
|
+
*
|
|
33
|
+
* Cache key: `strapi-article-<slug>`. Tags: `["articles", "article:<slug>"]`.
|
|
34
|
+
*/
|
|
35
|
+
export declare function fetchArticle(slug: string, { client, cache }: ContentDeps): Promise<StrapiArticle | null>;
|
|
36
|
+
//# sourceMappingURL=articles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"articles.d.ts","sourceRoot":"","sources":["../../src/content/articles.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAA0B,MAAM,oBAAoB,CAAC;AAOhF,4DAA4D;AAC5D,eAAO,MAAM,cAAc,0pBAsC1B,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,43BAmDjC,CAAC;AAEF,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAmB5F;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,GAC7B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAqB/B"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Article fetchers.
|
|
3
|
+
*
|
|
4
|
+
* Refactored from datum.net's `articles.ts`: same GraphQL queries and same
|
|
5
|
+
* primary-then-fallback read pattern, but the client and cache are injected
|
|
6
|
+
* rather than module-level singletons. Datum-specific transforms (block
|
|
7
|
+
* stripping, top-3 cover preservation, reading-time calculation) are
|
|
8
|
+
* intentionally not ported — those belong in application code.
|
|
9
|
+
*/
|
|
10
|
+
const LIST_CACHE_KEY = 'strapi-articles';
|
|
11
|
+
const DETAIL_CACHE_PREFIX = 'strapi-article-';
|
|
12
|
+
const FALLBACK_LIST_KEY = 'articles';
|
|
13
|
+
const FALLBACK_DETAIL_PREFIX = 'article-';
|
|
14
|
+
/** GraphQL query: every published article, newest first. */
|
|
15
|
+
export const ARTICLES_QUERY = `
|
|
16
|
+
query GetArticles {
|
|
17
|
+
articles(pagination: { limit: 100 }, sort: ["originalPublishedAt:desc"]) {
|
|
18
|
+
documentId
|
|
19
|
+
title
|
|
20
|
+
slug
|
|
21
|
+
description
|
|
22
|
+
originalPublishedAt
|
|
23
|
+
blocks {
|
|
24
|
+
__typename
|
|
25
|
+
... on ComponentSharedRichText {
|
|
26
|
+
id
|
|
27
|
+
body
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
cover {
|
|
31
|
+
url
|
|
32
|
+
alternativeText
|
|
33
|
+
width
|
|
34
|
+
height
|
|
35
|
+
formats
|
|
36
|
+
}
|
|
37
|
+
author {
|
|
38
|
+
documentId
|
|
39
|
+
slug
|
|
40
|
+
name
|
|
41
|
+
isTeam
|
|
42
|
+
avatar {
|
|
43
|
+
url
|
|
44
|
+
alternativeText
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
category {
|
|
48
|
+
name
|
|
49
|
+
slug
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
/** GraphQL query: a single article by slug, including SEO and quote blocks. */
|
|
55
|
+
export const ARTICLE_BY_SLUG_QUERY = `
|
|
56
|
+
query GetArticleBySlug($slug: String!) {
|
|
57
|
+
articles(filters: { slug: { eq: $slug } }) {
|
|
58
|
+
documentId
|
|
59
|
+
title
|
|
60
|
+
slug
|
|
61
|
+
description
|
|
62
|
+
originalPublishedAt
|
|
63
|
+
blocks {
|
|
64
|
+
__typename
|
|
65
|
+
... on ComponentSharedQuote {
|
|
66
|
+
body
|
|
67
|
+
title
|
|
68
|
+
}
|
|
69
|
+
... on ComponentSharedRichText {
|
|
70
|
+
id
|
|
71
|
+
body
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
cover {
|
|
75
|
+
url
|
|
76
|
+
alternativeText
|
|
77
|
+
width
|
|
78
|
+
height
|
|
79
|
+
formats
|
|
80
|
+
}
|
|
81
|
+
author {
|
|
82
|
+
documentId
|
|
83
|
+
slug
|
|
84
|
+
name
|
|
85
|
+
isTeam
|
|
86
|
+
avatar {
|
|
87
|
+
url
|
|
88
|
+
alternativeText
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
category {
|
|
92
|
+
name
|
|
93
|
+
slug
|
|
94
|
+
}
|
|
95
|
+
seo {
|
|
96
|
+
metaTitle
|
|
97
|
+
metaDescription
|
|
98
|
+
ogTitle
|
|
99
|
+
ogDescription
|
|
100
|
+
shareImage {
|
|
101
|
+
url
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
/**
|
|
108
|
+
* Fetch every article from Strapi. Reads from cache first; on Strapi failure,
|
|
109
|
+
* serves stale data from the persistent fallback cache instead of throwing.
|
|
110
|
+
*
|
|
111
|
+
* Cache key: `strapi-articles`. Tags: `["articles"]`.
|
|
112
|
+
*/
|
|
113
|
+
export async function fetchArticles({ client, cache }) {
|
|
114
|
+
const cached = await cache.get(LIST_CACHE_KEY);
|
|
115
|
+
if (cached)
|
|
116
|
+
return cached;
|
|
117
|
+
const response = await client.query(ARTICLES_QUERY);
|
|
118
|
+
if (!response?.articles) {
|
|
119
|
+
const fallback = await cache.getFallback(FALLBACK_LIST_KEY);
|
|
120
|
+
if (fallback) {
|
|
121
|
+
console.warn(`Strapi unreachable — serving ${fallback.length} articles from fallback`);
|
|
122
|
+
return fallback;
|
|
123
|
+
}
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
await cache.set(LIST_CACHE_KEY, response.articles, { tags: ['articles'] });
|
|
127
|
+
// Mirror to fallback under the legacy datum.net key so manual recovery is straightforward.
|
|
128
|
+
await cache.set(FALLBACK_LIST_KEY, response.articles, { tags: ['articles'] });
|
|
129
|
+
return response.articles;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Fetch a single article by slug. Cached per slug; falls back to stale
|
|
133
|
+
* data when Strapi is unreachable.
|
|
134
|
+
*
|
|
135
|
+
* Cache key: `strapi-article-<slug>`. Tags: `["articles", "article:<slug>"]`.
|
|
136
|
+
*/
|
|
137
|
+
export async function fetchArticle(slug, { client, cache }) {
|
|
138
|
+
const cacheKey = `${DETAIL_CACHE_PREFIX}${slug}`;
|
|
139
|
+
const cached = await cache.get(cacheKey);
|
|
140
|
+
if (cached)
|
|
141
|
+
return cached;
|
|
142
|
+
const response = await client.query(ARTICLE_BY_SLUG_QUERY, { slug });
|
|
143
|
+
if (!response?.articles || response.articles.length === 0) {
|
|
144
|
+
const fallback = await cache.getFallback(`${FALLBACK_DETAIL_PREFIX}${slug}`);
|
|
145
|
+
if (fallback) {
|
|
146
|
+
console.warn(`Strapi unreachable — serving article "${slug}" from fallback`);
|
|
147
|
+
return fallback;
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const article = response.articles[0];
|
|
152
|
+
const tags = ['articles', `article:${slug}`];
|
|
153
|
+
await cache.set(cacheKey, article, { tags });
|
|
154
|
+
await cache.set(`${FALLBACK_DETAIL_PREFIX}${slug}`, article, { tags });
|
|
155
|
+
return article;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=articles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"articles.js","sourceRoot":"","sources":["../../src/content/articles.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,cAAc,GAAG,iBAAiB,CAAC;AACzC,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAC9C,MAAM,iBAAiB,GAAG,UAAU,CAAC;AACrC,MAAM,sBAAsB,GAAG,UAAU,CAAC;AAE1C,4DAA4D;AAC5D,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsC7B,CAAC;AAEF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDpC,CAAC;AAQF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAe;IAChE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAkB,cAAc,CAAC,CAAC;IAChE,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAyB,cAAc,CAAC,CAAC;IAE5E,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAkB,iBAAiB,CAAC,CAAC;QAC7E,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,gCAAgC,QAAQ,CAAC,MAAM,yBAAyB,CAAC,CAAC;YACvF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC3E,2FAA2F;IAC3F,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC9E,OAAO,QAAQ,CAAC,QAAQ,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAY,EACZ,EAAE,MAAM,EAAE,KAAK,EAAe;IAE9B,MAAM,QAAQ,GAAG,GAAG,mBAAmB,GAAG,IAAI,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAgB,QAAQ,CAAC,CAAC;IACxD,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAyB,qBAAqB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7F,IAAI,CAAC,QAAQ,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAgB,GAAG,sBAAsB,GAAG,IAAI,EAAE,CAAC,CAAC;QAC5F,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,yCAAyC,IAAI,iBAAiB,CAAC,CAAC;YAC7E,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,sBAAsB,GAAG,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Author fetchers.
|
|
3
|
+
*
|
|
4
|
+
* Refactored from datum.net's `authors.ts`. Datum-specific concerns (team
|
|
5
|
+
* sorting, cardCategories normalization, color helpers) are intentionally
|
|
6
|
+
* out of scope — this module returns Strapi authors as-is.
|
|
7
|
+
*/
|
|
8
|
+
import type { StrapiAuthorFull } from '../types/strapi.js';
|
|
9
|
+
import type { ContentDeps } from './articles.js';
|
|
10
|
+
/** GraphQL query: every author. */
|
|
11
|
+
export declare const AUTHORS_QUERY = "\n query GetAuthors {\n authors(pagination: { limit: 100 }) {\n documentId\n slug\n name\n title\n bio\n isTeam\n team\n location\n timezone\n avatar {\n url\n alternativeText\n }\n social {\n twitter\n linkedin\n github\n discord\n email\n }\n }\n }\n";
|
|
12
|
+
/** GraphQL query: a single author by slug. */
|
|
13
|
+
export declare const AUTHOR_BY_SLUG_QUERY = "\n query GetAuthorBySlug($slug: String!) {\n authors(filters: { slug: { eq: $slug } }) {\n documentId\n slug\n name\n title\n bio\n isTeam\n team\n location\n timezone\n avatar {\n url\n alternativeText\n }\n social {\n twitter\n linkedin\n github\n discord\n email\n }\n }\n }\n";
|
|
14
|
+
/**
|
|
15
|
+
* Fetch every author from Strapi. Caches the list; falls back to stale data
|
|
16
|
+
* on Strapi failure.
|
|
17
|
+
*
|
|
18
|
+
* Cache key: `strapi-authors`. Tags: `["authors"]`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function fetchAuthors({ client, cache }: ContentDeps): Promise<StrapiAuthorFull[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Fetch a single author by slug. Cached per slug; falls back to stale data
|
|
23
|
+
* on Strapi failure.
|
|
24
|
+
*
|
|
25
|
+
* Cache key: `strapi-author-<slug>`. Tags: `["authors", "author:<slug>"]`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fetchAuthor(slug: string, { client, cache }: ContentDeps): Promise<StrapiAuthorFull | null>;
|
|
28
|
+
//# sourceMappingURL=authors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authors.d.ts","sourceRoot":"","sources":["../../src/content/authors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAOjD,mCAAmC;AACnC,eAAO,MAAM,aAAa,2XAyBzB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,oBAAoB,sZAyBhC,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkB9F;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,GAC7B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAqBlC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Author fetchers.
|
|
3
|
+
*
|
|
4
|
+
* Refactored from datum.net's `authors.ts`. Datum-specific concerns (team
|
|
5
|
+
* sorting, cardCategories normalization, color helpers) are intentionally
|
|
6
|
+
* out of scope — this module returns Strapi authors as-is.
|
|
7
|
+
*/
|
|
8
|
+
const LIST_CACHE_KEY = 'strapi-authors';
|
|
9
|
+
const DETAIL_CACHE_PREFIX = 'strapi-author-';
|
|
10
|
+
const FALLBACK_LIST_KEY = 'authors';
|
|
11
|
+
const FALLBACK_DETAIL_PREFIX = 'author-';
|
|
12
|
+
/** GraphQL query: every author. */
|
|
13
|
+
export const AUTHORS_QUERY = `
|
|
14
|
+
query GetAuthors {
|
|
15
|
+
authors(pagination: { limit: 100 }) {
|
|
16
|
+
documentId
|
|
17
|
+
slug
|
|
18
|
+
name
|
|
19
|
+
title
|
|
20
|
+
bio
|
|
21
|
+
isTeam
|
|
22
|
+
team
|
|
23
|
+
location
|
|
24
|
+
timezone
|
|
25
|
+
avatar {
|
|
26
|
+
url
|
|
27
|
+
alternativeText
|
|
28
|
+
}
|
|
29
|
+
social {
|
|
30
|
+
twitter
|
|
31
|
+
linkedin
|
|
32
|
+
github
|
|
33
|
+
discord
|
|
34
|
+
email
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
/** GraphQL query: a single author by slug. */
|
|
40
|
+
export const AUTHOR_BY_SLUG_QUERY = `
|
|
41
|
+
query GetAuthorBySlug($slug: String!) {
|
|
42
|
+
authors(filters: { slug: { eq: $slug } }) {
|
|
43
|
+
documentId
|
|
44
|
+
slug
|
|
45
|
+
name
|
|
46
|
+
title
|
|
47
|
+
bio
|
|
48
|
+
isTeam
|
|
49
|
+
team
|
|
50
|
+
location
|
|
51
|
+
timezone
|
|
52
|
+
avatar {
|
|
53
|
+
url
|
|
54
|
+
alternativeText
|
|
55
|
+
}
|
|
56
|
+
social {
|
|
57
|
+
twitter
|
|
58
|
+
linkedin
|
|
59
|
+
github
|
|
60
|
+
discord
|
|
61
|
+
email
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
/**
|
|
67
|
+
* Fetch every author from Strapi. Caches the list; falls back to stale data
|
|
68
|
+
* on Strapi failure.
|
|
69
|
+
*
|
|
70
|
+
* Cache key: `strapi-authors`. Tags: `["authors"]`.
|
|
71
|
+
*/
|
|
72
|
+
export async function fetchAuthors({ client, cache }) {
|
|
73
|
+
const cached = await cache.get(LIST_CACHE_KEY);
|
|
74
|
+
if (cached)
|
|
75
|
+
return cached;
|
|
76
|
+
const response = await client.query(AUTHORS_QUERY);
|
|
77
|
+
if (!response?.authors) {
|
|
78
|
+
const fallback = await cache.getFallback(FALLBACK_LIST_KEY);
|
|
79
|
+
if (fallback) {
|
|
80
|
+
console.warn(`Strapi unreachable — serving ${fallback.length} authors from fallback`);
|
|
81
|
+
return fallback;
|
|
82
|
+
}
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
await cache.set(LIST_CACHE_KEY, response.authors, { tags: ['authors'] });
|
|
86
|
+
await cache.set(FALLBACK_LIST_KEY, response.authors, { tags: ['authors'] });
|
|
87
|
+
return response.authors;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Fetch a single author by slug. Cached per slug; falls back to stale data
|
|
91
|
+
* on Strapi failure.
|
|
92
|
+
*
|
|
93
|
+
* Cache key: `strapi-author-<slug>`. Tags: `["authors", "author:<slug>"]`.
|
|
94
|
+
*/
|
|
95
|
+
export async function fetchAuthor(slug, { client, cache }) {
|
|
96
|
+
const cacheKey = `${DETAIL_CACHE_PREFIX}${slug}`;
|
|
97
|
+
const cached = await cache.get(cacheKey);
|
|
98
|
+
if (cached)
|
|
99
|
+
return cached;
|
|
100
|
+
const response = await client.query(AUTHOR_BY_SLUG_QUERY, { slug });
|
|
101
|
+
if (!response?.authors || response.authors.length === 0) {
|
|
102
|
+
const fallback = await cache.getFallback(`${FALLBACK_DETAIL_PREFIX}${slug}`);
|
|
103
|
+
if (fallback) {
|
|
104
|
+
console.warn(`Strapi unreachable — serving author "${slug}" from fallback`);
|
|
105
|
+
return fallback;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const author = response.authors[0];
|
|
110
|
+
const tags = ['authors', `author:${slug}`];
|
|
111
|
+
await cache.set(cacheKey, author, { tags });
|
|
112
|
+
await cache.set(`${FALLBACK_DETAIL_PREFIX}${slug}`, author, { tags });
|
|
113
|
+
return author;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=authors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authors.js","sourceRoot":"","sources":["../../src/content/authors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,cAAc,GAAG,gBAAgB,CAAC;AACxC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAC7C,MAAM,iBAAiB,GAAG,SAAS,CAAC;AACpC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAEzC,mCAAmC;AACnC,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyB5B,CAAC;AAEF,8CAA8C;AAC9C,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBnC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAe;IAC/D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAqB,cAAc,CAAC,CAAC;IACnE,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAwB,aAAa,CAAC,CAAC;IAE1E,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAqB,iBAAiB,CAAC,CAAC;QAChF,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,gCAAgC,QAAQ,CAAC,MAAM,wBAAwB,CAAC,CAAC;YACtF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,CAAC,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACzE,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,EAAE,QAAQ,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAC5E,OAAO,QAAQ,CAAC,OAAO,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAY,EACZ,EAAE,MAAM,EAAE,KAAK,EAAe;IAE9B,MAAM,QAAQ,GAAG,GAAG,mBAAmB,GAAG,IAAI,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAmB,QAAQ,CAAC,CAAC;IAC3D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAwB,oBAAoB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3F,IAAI,CAAC,QAAQ,EAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,CAAmB,GAAG,sBAAsB,GAAG,IAAI,EAAE,CAAC,CAAC;QAC/F,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,wCAAwC,IAAI,iBAAiB,CAAC,CAAC;YAC5E,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,sBAAsB,GAAG,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public content surface.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports every built-in fetcher and their GraphQL queries. Queries are
|
|
5
|
+
* exported as `const` strings so consumers can extend them with additional
|
|
6
|
+
* fields by composing their own query and passing it to the client directly.
|
|
7
|
+
*/
|
|
8
|
+
export type { ContentDeps } from './articles.js';
|
|
9
|
+
export { fetchArticles, fetchArticle, ARTICLES_QUERY, ARTICLE_BY_SLUG_QUERY, } from './articles.js';
|
|
10
|
+
export { fetchAuthors, fetchAuthor, AUTHORS_QUERY, AUTHOR_BY_SLUG_QUERY } from './authors.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public content surface.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports every built-in fetcher and their GraphQL queries. Queries are
|
|
5
|
+
* exported as `const` strings so consumers can extend them with additional
|
|
6
|
+
* fields by composing their own query and passing it to the client directly.
|
|
7
|
+
*/
|
|
8
|
+
export { fetchArticles, fetchArticle, ARTICLES_QUERY, ARTICLE_BY_SLUG_QUERY, } from './articles.js';
|
|
9
|
+
export { fetchAuthors, fetchAuthor, AUTHORS_QUERY, AUTHOR_BY_SLUG_QUERY } from './authors.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,qBAAqB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package root — re-exports the most commonly used API surface so most
|
|
3
|
+
* consumers can `import { createStrapiRevalidate } from 'strapi-revalidate'`
|
|
4
|
+
* and never touch the subpath imports.
|
|
5
|
+
*/
|
|
6
|
+
import type { CacheManager } from './cache/manager.js';
|
|
7
|
+
import type { StrapiClient } from './client/index.js';
|
|
8
|
+
import type { RevalidateConfig, RevalidateConfigInput } from './types/config.js';
|
|
9
|
+
import type { WebhookHandler } from './webhook/handler.js';
|
|
10
|
+
export * from './cache/index.js';
|
|
11
|
+
export * from './client/index.js';
|
|
12
|
+
export * from './content/index.js';
|
|
13
|
+
export * from './webhook/index.js';
|
|
14
|
+
export * from './types/strapi.js';
|
|
15
|
+
export { revalidateConfigSchema } from './types/config.js';
|
|
16
|
+
export type { RevalidateConfig, RevalidateConfigInput, CacheDriverName, TransportName, } from './types/config.js';
|
|
17
|
+
/** Bundle of objects returned by `createStrapiRevalidate`. */
|
|
18
|
+
export interface StrapiRevalidate {
|
|
19
|
+
config: RevalidateConfig;
|
|
20
|
+
client: StrapiClient;
|
|
21
|
+
cache: CacheManager;
|
|
22
|
+
/** Pre-built webhook handler bound to this `client`/`cache` pair. */
|
|
23
|
+
webhook: WebhookHandler;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* One-call factory that validates config, builds the client, cache manager,
|
|
27
|
+
* and webhook handler, and returns them as a single object.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const { cache, client, webhook } = createStrapiRevalidate({
|
|
31
|
+
* url: process.env.STRAPI_URL!,
|
|
32
|
+
* token: process.env.STRAPI_TOKEN!,
|
|
33
|
+
* webhook: { secret: process.env.STRAPI_WEBHOOK_SECRET },
|
|
34
|
+
* });
|
|
35
|
+
*/
|
|
36
|
+
export declare function createStrapiRevalidate(input: RevalidateConfigInput): StrapiRevalidate;
|
|
37
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,qEAAqE;IACrE,OAAO,EAAE,cAAc,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,CAMrF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package root — re-exports the most commonly used API surface so most
|
|
3
|
+
* consumers can `import { createStrapiRevalidate } from 'strapi-revalidate'`
|
|
4
|
+
* and never touch the subpath imports.
|
|
5
|
+
*/
|
|
6
|
+
import { createCache } from './cache/index.js';
|
|
7
|
+
import { createStrapiClient } from './client/index.js';
|
|
8
|
+
import { revalidateConfigSchema } from './types/config.js';
|
|
9
|
+
import { createWebhookHandler } from './webhook/handler.js';
|
|
10
|
+
// Subpath re-exports (mirrors the package.json exports map).
|
|
11
|
+
export * from './cache/index.js';
|
|
12
|
+
export * from './client/index.js';
|
|
13
|
+
export * from './content/index.js';
|
|
14
|
+
export * from './webhook/index.js';
|
|
15
|
+
export * from './types/strapi.js';
|
|
16
|
+
export { revalidateConfigSchema } from './types/config.js';
|
|
17
|
+
/**
|
|
18
|
+
* One-call factory that validates config, builds the client, cache manager,
|
|
19
|
+
* and webhook handler, and returns them as a single object.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const { cache, client, webhook } = createStrapiRevalidate({
|
|
23
|
+
* url: process.env.STRAPI_URL!,
|
|
24
|
+
* token: process.env.STRAPI_TOKEN!,
|
|
25
|
+
* webhook: { secret: process.env.STRAPI_WEBHOOK_SECRET },
|
|
26
|
+
* });
|
|
27
|
+
*/
|
|
28
|
+
export function createStrapiRevalidate(input) {
|
|
29
|
+
const config = revalidateConfigSchema.parse(input);
|
|
30
|
+
const cache = createCache(config);
|
|
31
|
+
const client = createStrapiClient(config);
|
|
32
|
+
const webhook = createWebhookHandler({ config, cache });
|
|
33
|
+
return { config, client, cache, webhook };
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAG5D,6DAA6D;AAC7D,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAiB3D;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAA4B;IACjE,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,oBAAoB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime configuration schema for strapi-revalidate.
|
|
3
|
+
*
|
|
4
|
+
* Validated with zod so misconfigurations surface at startup rather than
|
|
5
|
+
* at the first cache miss or webhook delivery.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { WebhookEvent } from '../webhook/types.js';
|
|
9
|
+
/** Supported cache driver identifiers. */
|
|
10
|
+
export declare const cacheDriverNameSchema: z.ZodEnum<["file", "memory", "redis"]>;
|
|
11
|
+
export type CacheDriverName = z.infer<typeof cacheDriverNameSchema>;
|
|
12
|
+
/** Supported transport identifiers for the Strapi client. */
|
|
13
|
+
export declare const transportNameSchema: z.ZodEnum<["graphql", "rest"]>;
|
|
14
|
+
export type TransportName = z.infer<typeof transportNameSchema>;
|
|
15
|
+
/**
|
|
16
|
+
* Full runtime configuration schema.
|
|
17
|
+
*
|
|
18
|
+
* Use `revalidateConfigSchema.parse(input)` to validate user input and
|
|
19
|
+
* apply defaults in one step.
|
|
20
|
+
*/
|
|
21
|
+
export declare const revalidateConfigSchema: z.ZodObject<{
|
|
22
|
+
url: z.ZodString;
|
|
23
|
+
token: z.ZodString;
|
|
24
|
+
webhook: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
secret: z.ZodOptional<z.ZodString>;
|
|
26
|
+
tagMap: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
27
|
+
onRevalidate: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodType<WebhookEvent, z.ZodTypeDef, WebhookEvent>], z.ZodUnknown>, z.ZodUnion<[z.ZodVoid, z.ZodPromise<z.ZodVoid>]>>>;
|
|
28
|
+
}, "strip", z.ZodTypeAny, {
|
|
29
|
+
secret?: string | undefined;
|
|
30
|
+
tagMap?: Record<string, string[]> | undefined;
|
|
31
|
+
onRevalidate?: ((args_0: WebhookEvent, ...args: unknown[]) => void | Promise<void>) | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
secret?: string | undefined;
|
|
34
|
+
tagMap?: Record<string, string[]> | undefined;
|
|
35
|
+
onRevalidate?: ((args_0: WebhookEvent, ...args: unknown[]) => void | Promise<void>) | undefined;
|
|
36
|
+
}>>;
|
|
37
|
+
cache: z.ZodDefault<z.ZodObject<{
|
|
38
|
+
driver: z.ZodDefault<z.ZodEnum<["file", "memory", "redis"]>>;
|
|
39
|
+
ttl: z.ZodDefault<z.ZodNumber>;
|
|
40
|
+
dir: z.ZodDefault<z.ZodString>;
|
|
41
|
+
fallbackDir: z.ZodDefault<z.ZodString>;
|
|
42
|
+
redisUrl: z.ZodOptional<z.ZodString>;
|
|
43
|
+
keyPrefix: z.ZodOptional<z.ZodString>;
|
|
44
|
+
}, "strip", z.ZodTypeAny, {
|
|
45
|
+
driver: "file" | "memory" | "redis";
|
|
46
|
+
ttl: number;
|
|
47
|
+
dir: string;
|
|
48
|
+
fallbackDir: string;
|
|
49
|
+
redisUrl?: string | undefined;
|
|
50
|
+
keyPrefix?: string | undefined;
|
|
51
|
+
}, {
|
|
52
|
+
driver?: "file" | "memory" | "redis" | undefined;
|
|
53
|
+
ttl?: number | undefined;
|
|
54
|
+
dir?: string | undefined;
|
|
55
|
+
fallbackDir?: string | undefined;
|
|
56
|
+
redisUrl?: string | undefined;
|
|
57
|
+
keyPrefix?: string | undefined;
|
|
58
|
+
}>>;
|
|
59
|
+
transport: z.ZodDefault<z.ZodEnum<["graphql", "rest"]>>;
|
|
60
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
61
|
+
retry: z.ZodDefault<z.ZodNumber>;
|
|
62
|
+
debug: z.ZodDefault<z.ZodBoolean>;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
url: string;
|
|
65
|
+
token: string;
|
|
66
|
+
cache: {
|
|
67
|
+
driver: "file" | "memory" | "redis";
|
|
68
|
+
ttl: number;
|
|
69
|
+
dir: string;
|
|
70
|
+
fallbackDir: string;
|
|
71
|
+
redisUrl?: string | undefined;
|
|
72
|
+
keyPrefix?: string | undefined;
|
|
73
|
+
};
|
|
74
|
+
transport: "graphql" | "rest";
|
|
75
|
+
timeout: number;
|
|
76
|
+
retry: number;
|
|
77
|
+
debug: boolean;
|
|
78
|
+
webhook?: {
|
|
79
|
+
secret?: string | undefined;
|
|
80
|
+
tagMap?: Record<string, string[]> | undefined;
|
|
81
|
+
onRevalidate?: ((args_0: WebhookEvent, ...args: unknown[]) => void | Promise<void>) | undefined;
|
|
82
|
+
} | undefined;
|
|
83
|
+
}, {
|
|
84
|
+
url: string;
|
|
85
|
+
token: string;
|
|
86
|
+
webhook?: {
|
|
87
|
+
secret?: string | undefined;
|
|
88
|
+
tagMap?: Record<string, string[]> | undefined;
|
|
89
|
+
onRevalidate?: ((args_0: WebhookEvent, ...args: unknown[]) => void | Promise<void>) | undefined;
|
|
90
|
+
} | undefined;
|
|
91
|
+
cache?: {
|
|
92
|
+
driver?: "file" | "memory" | "redis" | undefined;
|
|
93
|
+
ttl?: number | undefined;
|
|
94
|
+
dir?: string | undefined;
|
|
95
|
+
fallbackDir?: string | undefined;
|
|
96
|
+
redisUrl?: string | undefined;
|
|
97
|
+
keyPrefix?: string | undefined;
|
|
98
|
+
} | undefined;
|
|
99
|
+
transport?: "graphql" | "rest" | undefined;
|
|
100
|
+
timeout?: number | undefined;
|
|
101
|
+
retry?: number | undefined;
|
|
102
|
+
debug?: boolean | undefined;
|
|
103
|
+
}>;
|
|
104
|
+
/** User-supplied configuration (pre-validation). */
|
|
105
|
+
export type RevalidateConfigInput = z.input<typeof revalidateConfigSchema>;
|
|
106
|
+
/** Validated, defaults-applied configuration. */
|
|
107
|
+
export type RevalidateConfig = z.output<typeof revalidateConfigSchema>;
|
|
108
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB,wCAAsC,CAAC;AACzE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB,gCAA8B,CAAC;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAyBhE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASjC,CAAC;AAEH,oDAAoD;AACpD,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE3E,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime configuration schema for strapi-revalidate.
|
|
3
|
+
*
|
|
4
|
+
* Validated with zod so misconfigurations surface at startup rather than
|
|
5
|
+
* at the first cache miss or webhook delivery.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
/** Supported cache driver identifiers. */
|
|
9
|
+
export const cacheDriverNameSchema = z.enum(['file', 'memory', 'redis']);
|
|
10
|
+
/** Supported transport identifiers for the Strapi client. */
|
|
11
|
+
export const transportNameSchema = z.enum(['graphql', 'rest']);
|
|
12
|
+
const cacheConfigSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
driver: cacheDriverNameSchema.default('file'),
|
|
15
|
+
ttl: z.number().int().positive().default(3600),
|
|
16
|
+
dir: z.string().default('.cache/strapi-revalidate'),
|
|
17
|
+
fallbackDir: z.string().default('.cache/strapi-fallback'),
|
|
18
|
+
redisUrl: z.string().url().optional(),
|
|
19
|
+
keyPrefix: z.string().optional(),
|
|
20
|
+
})
|
|
21
|
+
.default({});
|
|
22
|
+
const webhookConfigSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
secret: z.string().optional(),
|
|
25
|
+
tagMap: z.record(z.array(z.string())).optional(),
|
|
26
|
+
onRevalidate: z
|
|
27
|
+
.function()
|
|
28
|
+
.args(z.custom())
|
|
29
|
+
.returns(z.union([z.void(), z.promise(z.void())]))
|
|
30
|
+
.optional(),
|
|
31
|
+
})
|
|
32
|
+
.optional();
|
|
33
|
+
/**
|
|
34
|
+
* Full runtime configuration schema.
|
|
35
|
+
*
|
|
36
|
+
* Use `revalidateConfigSchema.parse(input)` to validate user input and
|
|
37
|
+
* apply defaults in one step.
|
|
38
|
+
*/
|
|
39
|
+
export const revalidateConfigSchema = z.object({
|
|
40
|
+
url: z.string().url(),
|
|
41
|
+
token: z.string().min(1),
|
|
42
|
+
webhook: webhookConfigSchema,
|
|
43
|
+
cache: cacheConfigSchema,
|
|
44
|
+
transport: transportNameSchema.default('graphql'),
|
|
45
|
+
timeout: z.number().int().positive().default(3000),
|
|
46
|
+
retry: z.number().int().min(0).default(2),
|
|
47
|
+
debug: z.boolean().default(false),
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,0CAA0C;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAGzE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAG/D,MAAM,iBAAiB,GAAG,CAAC;KACxB,MAAM,CAAC;IACN,MAAM,EAAE,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC;IACnD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC;IACzD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC;KACD,OAAO,CAAC,EAAE,CAAC,CAAC;AAEf,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChD,YAAY,EAAE,CAAC;SACZ,QAAQ,EAAE;SACV,IAAI,CAAC,CAAC,CAAC,MAAM,EAAgB,CAAC;SAC9B,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;SACjD,QAAQ,EAAE;CACd,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,mBAAmB;IAC5B,KAAK,EAAE,iBAAiB;IACxB,SAAS,EAAE,mBAAmB,CAAC,OAAO,CAAC,SAAS,CAAC;IACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACzC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CAClC,CAAC,CAAC"}
|