astro-loader-pocketbase 0.3.0-rc.1 → 0.3.0-rc.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/package.json +3 -3
- package/src/generate-schema.ts +15 -1
- package/src/load-entries.ts +1 -1
- package/src/pocketbase-loader.ts +13 -0
- package/src/types/pocketbase-loader-options.type.ts +1 -1
- package/src/utils/parse-entry.ts +11 -1
- package/src/utils/parse-schema.ts +2 -1
- package/src/utils/transform-files.ts +66 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-loader-pocketbase",
|
|
3
|
-
"version": "0.3.0-rc.
|
|
3
|
+
"version": "0.3.0-rc.3",
|
|
4
4
|
"description": "A content loader for Astro that uses the PocketBase API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Luis Wolf <development@pawcode.de> (https://pawcode.de)",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@eslint/js": "^9.11.1",
|
|
25
25
|
"@stylistic/eslint-plugin": "^2.8.0",
|
|
26
|
-
"@types/node": "^22.
|
|
27
|
-
"astro": "^5.0.0-beta.
|
|
26
|
+
"@types/node": "^22.7.4",
|
|
27
|
+
"astro": "^5.0.0-beta.2",
|
|
28
28
|
"eslint": "^9.11.1",
|
|
29
29
|
"globals": "^15.9.0",
|
|
30
30
|
"husky": "^9.1.6",
|
package/src/generate-schema.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { PocketBaseCollection } from "./types/pocketbase-schema.type";
|
|
|
5
5
|
import { getRemoteSchema } from "./utils/get-remote-schema";
|
|
6
6
|
import { parseSchema } from "./utils/parse-schema";
|
|
7
7
|
import { readLocalSchema } from "./utils/read-local-schema";
|
|
8
|
+
import { transformFiles } from "./utils/transform-files";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Basic schema for every PocketBase collection.
|
|
@@ -84,8 +85,21 @@ export async function generateSchema(
|
|
|
84
85
|
const base = collection.type === "view" ? VIEW_SCHEMA : BASIC_SCHEMA;
|
|
85
86
|
|
|
86
87
|
// Combine the basic schema with the parsed fields
|
|
87
|
-
|
|
88
|
+
const schema = z.object({
|
|
88
89
|
...base,
|
|
89
90
|
...fields
|
|
90
91
|
});
|
|
92
|
+
|
|
93
|
+
// Get all file fields
|
|
94
|
+
const fileFields = collection.schema.filter((field) => field.type === "file");
|
|
95
|
+
|
|
96
|
+
if (fileFields.length === 0) {
|
|
97
|
+
return schema;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Transform file names to file urls
|
|
101
|
+
return schema.transform((entry) =>
|
|
102
|
+
// @ts-expect-error - `updated` and `created` are already transformed to dates
|
|
103
|
+
transformFiles(options.url, fileFields, entry)
|
|
104
|
+
);
|
|
91
105
|
}
|
package/src/load-entries.ts
CHANGED
package/src/pocketbase-loader.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Loader, LoaderContext } from "astro/loaders";
|
|
2
|
+
import packageJson from "./../package.json";
|
|
2
3
|
import { cleanupEntries } from "./cleanup-entries";
|
|
3
4
|
import { generateSchema } from "./generate-schema";
|
|
4
5
|
import { loadEntries } from "./load-entries";
|
|
@@ -14,6 +15,16 @@ export function pocketbaseLoader(options: PocketBaseLoaderOptions): Loader {
|
|
|
14
15
|
return {
|
|
15
16
|
name: "pocketbase-loader",
|
|
16
17
|
load: async (context: LoaderContext): Promise<void> => {
|
|
18
|
+
// Check if the version has changed to force an update
|
|
19
|
+
const lastVersion = context.meta.get("version");
|
|
20
|
+
if (lastVersion !== packageJson.version) {
|
|
21
|
+
context.logger.info(
|
|
22
|
+
`PocketBase loader was updated from ${lastVersion} to ${packageJson.version}. All entries will be loaded again.`
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
options.forceUpdate = true;
|
|
26
|
+
}
|
|
27
|
+
|
|
17
28
|
// Get the date of the last fetch to only update changed entries.
|
|
18
29
|
// If `forceUpdate` is set to `true`, this will be `undefined` to fetch all entries again.
|
|
19
30
|
const lastModified = options.forceUpdate
|
|
@@ -67,6 +78,8 @@ export function pocketbaseLoader(options: PocketBaseLoaderOptions): Loader {
|
|
|
67
78
|
|
|
68
79
|
// Set the last modified date to the current date
|
|
69
80
|
context.meta.set("last-modified", new Date().toISOString());
|
|
81
|
+
|
|
82
|
+
context.meta.set("version", packageJson.version);
|
|
70
83
|
},
|
|
71
84
|
schema: async () => {
|
|
72
85
|
// Generate the schema for the collection according to the API
|
|
@@ -19,7 +19,7 @@ export interface PocketBaseLoaderOptions {
|
|
|
19
19
|
* The loader will concatenate the content of all fields in the order they are defined in the array.
|
|
20
20
|
* Each block will be contained in a `<section>` element.
|
|
21
21
|
*/
|
|
22
|
-
content
|
|
22
|
+
content?: string | Array<string>;
|
|
23
23
|
/**
|
|
24
24
|
* Email of an admin to get full access to the PocketBase instance.
|
|
25
25
|
* Together with `adminPassword` this is required to get automatic type generation and to access all resources even if they are not public.
|
package/src/utils/parse-entry.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { PocketBaseEntry } from "../types/pocketbase-entry.type";
|
|
|
12
12
|
export async function parseEntry(
|
|
13
13
|
entry: PocketBaseEntry,
|
|
14
14
|
{ generateDigest, parseData, store }: LoaderContext,
|
|
15
|
-
contentFields
|
|
15
|
+
contentFields?: string | Array<string>
|
|
16
16
|
): Promise<void> {
|
|
17
17
|
// Parse the data to match the schema
|
|
18
18
|
// This will throw an error if the data does not match the schema
|
|
@@ -27,6 +27,16 @@ export async function parseEntry(
|
|
|
27
27
|
// View collections don't necessarily publish the updated date, so the whole entry is used for the digest.
|
|
28
28
|
const digest = generateDigest(entry.updated ?? entry.created ?? entry);
|
|
29
29
|
|
|
30
|
+
if (!contentFields) {
|
|
31
|
+
// Store the entry
|
|
32
|
+
store.set({
|
|
33
|
+
id: entry.id,
|
|
34
|
+
data,
|
|
35
|
+
digest
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
30
40
|
// Generate the content for the entry
|
|
31
41
|
let content: string;
|
|
32
42
|
if (typeof contentFields === "string") {
|
|
@@ -44,7 +44,8 @@ export function parseSchema(
|
|
|
44
44
|
break;
|
|
45
45
|
case "relation":
|
|
46
46
|
case "file":
|
|
47
|
-
// NOTE: Relations
|
|
47
|
+
// NOTE: Relations are currently not supported and are treated as strings
|
|
48
|
+
// NOTE: Files are later transformed to URLs
|
|
48
49
|
|
|
49
50
|
// Parse the field type based on the number of values it can have
|
|
50
51
|
fieldType = parseSingleOrMultipleValues(field, z.string());
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { PocketBaseEntry } from "../types/pocketbase-entry.type";
|
|
2
|
+
import type { PocketBaseSchemaEntry } from "../types/pocketbase-schema.type";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Transforms file names in a PocketBase entry to file URLs.
|
|
6
|
+
*
|
|
7
|
+
* @param baseUrl URL of the PocketBase instance.
|
|
8
|
+
* @param collection Collection of the entry.
|
|
9
|
+
* @param entry Entry to transform.
|
|
10
|
+
*/
|
|
11
|
+
export function transformFiles(
|
|
12
|
+
baseUrl: string,
|
|
13
|
+
fileFields: Array<PocketBaseSchemaEntry>,
|
|
14
|
+
entry: PocketBaseEntry
|
|
15
|
+
): PocketBaseEntry {
|
|
16
|
+
// Transform all file names to file URLs
|
|
17
|
+
for (const field of fileFields) {
|
|
18
|
+
const fieldName = field.name;
|
|
19
|
+
|
|
20
|
+
if (field.options.maxSelect === 1) {
|
|
21
|
+
const fileName = entry[fieldName] as string | undefined;
|
|
22
|
+
// Check if a file name is present
|
|
23
|
+
if (!fileName) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Transform the file name to a file URL
|
|
28
|
+
entry[fieldName] = transformFileUrl(
|
|
29
|
+
baseUrl,
|
|
30
|
+
entry.collectionName,
|
|
31
|
+
entry.id,
|
|
32
|
+
fileName
|
|
33
|
+
);
|
|
34
|
+
} else {
|
|
35
|
+
const fileNames = entry[fieldName] as Array<string> | undefined;
|
|
36
|
+
// Check if file names are present
|
|
37
|
+
if (!fileNames) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Transform all file names to file URLs
|
|
42
|
+
entry[fieldName] = fileNames.map((file) =>
|
|
43
|
+
transformFileUrl(baseUrl, entry.collectionName, entry.id, file)
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return entry;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Transforms a file name to a PocketBase file URL.
|
|
53
|
+
*
|
|
54
|
+
* @param base Base URL of the PocketBase instance.
|
|
55
|
+
* @param collectionName Name of the collection.
|
|
56
|
+
* @param entryId ID of the entry.
|
|
57
|
+
* @param file Name of the file.
|
|
58
|
+
*/
|
|
59
|
+
function transformFileUrl(
|
|
60
|
+
base: string,
|
|
61
|
+
collectionName: string,
|
|
62
|
+
entryId: string,
|
|
63
|
+
file: string
|
|
64
|
+
): string {
|
|
65
|
+
return `${base}/api/files/${collectionName}/${entryId}/${file}`;
|
|
66
|
+
}
|