summaryrefslogtreecommitdiffstats
path: root/src/deps/strapi.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/deps/strapi.ts')
-rw-r--r--src/deps/strapi.ts110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/deps/strapi.ts b/src/deps/strapi.ts
new file mode 100644
index 0000000..32e49b0
--- /dev/null
+++ b/src/deps/strapi.ts
@@ -0,0 +1,110 @@
1import type { Pipeline, PipelineStageError } from "corvos";
2import type { StandardSchemaV1, StandardTypedV1 } from "corvos/deps/standard_schema.ts";
3
4import { Page } from "corvos";
5import { replaceExtension } from "corvos/core/utils/path.ts";
6
7import type { Node } from "./strapi/schema.ts";
8
9import { blocksToTSX } from "./strapi/blocks.tsx";
10import { StrapiLoader } from "./strapi/loader.ts";
11
12export type { Node } from "./strapi/schema.ts";
13export { nodeSchema, fileAttributeSchema, imageAttributeSchema } from "./strapi/schema.ts";
14export { Blocks } from "./strapi/blocks.tsx";
15
16export interface StrapiContent<Type extends "single" | "collection" = "single" | "collection"> {
17 type: Type;
18 schema: StandardSchemaV1;
19 query?: Record<string, string>;
20}
21
22type ContentSingle<T extends Record<string, StrapiContent>> = {
23 [Key in keyof T]: T[Key]["type"] extends "single" ? Key : never;
24}[keyof T];
25
26type ContentCollection<T extends Record<string, StrapiContent>> = {
27 [Key in keyof T]: T[Key]["type"] extends "collection" ? Key : never;
28}[keyof T];
29
30export interface Options<Content extends Record<string, StrapiContent>> {
31 url: string;
32 token: string;
33 content: Content;
34}
35
36export function strapi<Content extends Record<string, StrapiContent>>(options: Options<Content>) {
37 const loader = new StrapiLoader(options.url, options.token);
38
39 function load<const Key extends ContentSingle<Content> & string>(
40 key: Key,
41 query?: Record<string, string>,
42 ): Promise<
43 {
44 documentId: string;
45 publishedAt: Date | null;
46 updatedAt: Date;
47 } & StandardTypedV1.InferOutput<Content[Key]["schema"]>
48 >;
49 function load<const Key extends ContentCollection<Content> & string>(
50 key: Key,
51 query?: Record<string, string>,
52 ): AsyncGenerator<
53 | PipelineStageError
54 | ({
55 documentId: string;
56 publishedAt: Date | null;
57 updatedAt: Date;
58 } & StandardTypedV1.InferOutput<Content[Key]["schema"]>),
59 void,
60 unknown
61 >;
62 function load<const Key extends Content & string>(
63 key: Key,
64 query?: Record<string, string>,
65 ):
66 | Promise<
67 {
68 documentId: string;
69 publishedAt: Date | null;
70 updatedAt: Date;
71 } & StandardTypedV1.InferOutput<Content[Key]["schema"]>
72 >
73 | AsyncGenerator<
74 | PipelineStageError
75 | ({
76 documentId: string;
77 publishedAt: Date | null;
78 updatedAt: Date;
79 } & StandardTypedV1.InferOutput<Content[Key]["schema"]>),
80 void,
81 unknown
82 > {
83 if (options.content[key]!.type === "single") {
84 return loader.loadSingle(key, options.content[key]!.schema, {
85 ...options.content[key]!.query,
86 ...query,
87 });
88 } else {
89 return loader.loadCollection(key, options.content[key]!.schema, {
90 ...options.content[key]!.query,
91 ...query,
92 });
93 }
94 }
95
96 return <Loaders extends string, Out extends { ".strapi": [Node[], {}] }, Helpers extends {}>(
97 pipeline: Pipeline<Loaders, Out, Helpers>,
98 ) =>
99 pipeline
100 .process("strapi", ".strapi", function* (page) {
101 yield new Page(
102 ".jsxelement",
103 blocksToTSX(page.content),
104 page.data as Out[".strapi"][1],
105 replaceExtension(page.url, ".jsx"),
106 page,
107 );
108 })
109 .helper("strapi", load);
110}