astro-loader-pocketbase 3.1.0 → 3.1.2-next.1
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/dist/index.d.mts +276 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +973 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +24 -15
- package/src/index.ts +0 -24
- package/src/loader/cleanup-entries.ts +0 -137
- package/src/loader/fetch-collection.ts +0 -177
- package/src/loader/fetch-entry.ts +0 -83
- package/src/loader/handle-realtime-updates.ts +0 -56
- package/src/loader/live-collection-loader.ts +0 -51
- package/src/loader/live-entry-loader.ts +0 -38
- package/src/loader/load-entries.ts +0 -52
- package/src/loader/loader.ts +0 -77
- package/src/loader/parse-entry.ts +0 -90
- package/src/loader/parse-live-entry.ts +0 -66
- package/src/pocketbase-loader.ts +0 -98
- package/src/schema/generate-schema.ts +0 -200
- package/src/schema/generate-type.ts +0 -23
- package/src/schema/get-remote-schema.ts +0 -43
- package/src/schema/parse-schema.ts +0 -170
- package/src/schema/read-local-schema.ts +0 -46
- package/src/schema/transform-files.ts +0 -67
- package/src/tsconfig.json +0 -7
- package/src/types/errors.ts +0 -19
- package/src/types/pocketbase-api-response.type.ts +0 -40
- package/src/types/pocketbase-entry.type.ts +0 -24
- package/src/types/pocketbase-live-loader-filter.type.ts +0 -55
- package/src/types/pocketbase-loader-options.type.ts +0 -146
- package/src/types/pocketbase-schema.type.ts +0 -101
- package/src/utils/combine-fields-for-request.ts +0 -55
- package/src/utils/create-token-promise.ts +0 -25
- package/src/utils/extract-field-names.ts +0 -15
- package/src/utils/format-fields.ts +0 -66
- package/src/utils/get-superuser-token.ts +0 -76
- package/src/utils/is-realtime-data.ts +0 -34
- package/src/utils/should-refresh.ts +0 -37
- package/src/utils/slugify.ts +0 -21
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filter for a single entry
|
|
3
|
-
*/
|
|
4
|
-
export interface PocketBaseLiveLoaderEntryFilter {
|
|
5
|
-
/**
|
|
6
|
-
* Id of the entry.
|
|
7
|
-
*/
|
|
8
|
-
id: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Filter for a collection of entries.
|
|
13
|
-
*/
|
|
14
|
-
export interface PocketBaseLiveLoaderCollectionFilter {
|
|
15
|
-
/**
|
|
16
|
-
* Additional filter to apply to the collection.
|
|
17
|
-
* This will be added to the filter supplied in the {@link PocketBaseLiveLoaderOptions}.
|
|
18
|
-
*
|
|
19
|
-
* Example:
|
|
20
|
-
* ```ts
|
|
21
|
-
* // config:
|
|
22
|
-
* filter: 'release >= @now && deleted = false'
|
|
23
|
-
*
|
|
24
|
-
* // request
|
|
25
|
-
* `?filter=(${loaderFilter})&&(release >= @now && deleted = false)`
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* @see {@link https://pocketbase.io/docs/api-records/#listsearch-records PocketBase documentation} for valid syntax
|
|
29
|
-
*/
|
|
30
|
-
filter?: string;
|
|
31
|
-
/**
|
|
32
|
-
* Page number to load (1-indexed).
|
|
33
|
-
*/
|
|
34
|
-
page?: number;
|
|
35
|
-
/**
|
|
36
|
-
* Number of entries to load per page.
|
|
37
|
-
* If not provided all entries will be loaded in chunks of 100.
|
|
38
|
-
*/
|
|
39
|
-
perPage?: number;
|
|
40
|
-
/**
|
|
41
|
-
* Sort order in which the entries should be returned.
|
|
42
|
-
*
|
|
43
|
-
* Example:
|
|
44
|
-
* ```ts
|
|
45
|
-
* // config:
|
|
46
|
-
* sort: '-created,id'
|
|
47
|
-
*
|
|
48
|
-
* // request
|
|
49
|
-
* `?sort=-created,id`
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* @see {@link https://pocketbase.io/docs/api-records/#listsearch-records PocketBase documentation} for valid syntax
|
|
53
|
-
*/
|
|
54
|
-
sort?: string;
|
|
55
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import type { ZodType } from "astro/zod";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Options for both build time and live collection loader
|
|
5
|
-
*/
|
|
6
|
-
export interface PocketBaseLoaderBaseOptions {
|
|
7
|
-
/**
|
|
8
|
-
* URL of the PocketBase instance.
|
|
9
|
-
*/
|
|
10
|
-
url: string;
|
|
11
|
-
/**
|
|
12
|
-
* Name of the collection in PocketBase.
|
|
13
|
-
*/
|
|
14
|
-
collectionName: string;
|
|
15
|
-
/**
|
|
16
|
-
* Name of the field(s) containing the content of an entry.
|
|
17
|
-
* This must be the name of a field in the PocketBase collection that contains the content.
|
|
18
|
-
* The content will be parsed as HTML and rendered to the page.
|
|
19
|
-
*
|
|
20
|
-
* If you want to render multiple fields as main content, you can pass an array of field names.
|
|
21
|
-
* The loader will concatenate the content of all fields in the order they are defined in the array.
|
|
22
|
-
* Each block will be contained in a `<section>` element.
|
|
23
|
-
*/
|
|
24
|
-
contentFields?: string | Array<string>;
|
|
25
|
-
/**
|
|
26
|
-
* Name of the field containing the last update date of an entry.
|
|
27
|
-
* Ideally, this field should be of type `autodate` and have the value "Update" or "Create/Update".
|
|
28
|
-
* For the build time loader, this field is used to only fetch entries that have been modified since the last build.
|
|
29
|
-
* For the live collection loader, this field is used to set the `lastModified` cache hint.
|
|
30
|
-
*/
|
|
31
|
-
updatedField?: string;
|
|
32
|
-
/**
|
|
33
|
-
* Custom filter that is applied when loading data from PocketBase.
|
|
34
|
-
*
|
|
35
|
-
* The loader will also add it's own filters for incremental builds.
|
|
36
|
-
* These will be added to your custom filter query.
|
|
37
|
-
*
|
|
38
|
-
* Example:
|
|
39
|
-
* ```ts
|
|
40
|
-
* // config:
|
|
41
|
-
* filter: 'release >= @now && deleted = false'
|
|
42
|
-
*
|
|
43
|
-
* // request
|
|
44
|
-
* `?filter=(${loaderFilter})&&(release >= @now && deleted = false)`
|
|
45
|
-
* ```
|
|
46
|
-
*
|
|
47
|
-
* @see {@link https://pocketbase.io/docs/api-records/#listsearch-records PocketBase documentation} for valid syntax
|
|
48
|
-
*/
|
|
49
|
-
filter?: string;
|
|
50
|
-
/**
|
|
51
|
-
* Specify which fields to return for each record.
|
|
52
|
-
* This can be either a comma-separated string of field names or an array of field names.
|
|
53
|
-
* Only the specified fields will be included in the response and schema.
|
|
54
|
-
*
|
|
55
|
-
* Use "*" to include all fields (same as not specifying the fields option).
|
|
56
|
-
*
|
|
57
|
-
* Note: The basic fields (`id`, `collectionId`, `collectionName`) are automatically included
|
|
58
|
-
* in API requests when using field filtering. Additionally, any custom fields specified in the
|
|
59
|
-
* loader options (`idField`, `updatedField`, `contentFields`) are also automatically included.
|
|
60
|
-
*
|
|
61
|
-
* Warning: Expand fields are not currently supported by this loader.
|
|
62
|
-
*
|
|
63
|
-
* Example:
|
|
64
|
-
* ```ts
|
|
65
|
-
* // Using string format:
|
|
66
|
-
* fields: 'title,content,author'
|
|
67
|
-
*
|
|
68
|
-
* // Using array format:
|
|
69
|
-
* fields: ['title', 'content', 'author']
|
|
70
|
-
*
|
|
71
|
-
* // Include all fields:
|
|
72
|
-
* fields: '*'
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* @see {@link https://pocketbase.io/docs/api-records/#listsearch-records PocketBase documentation} for valid syntax
|
|
76
|
-
*/
|
|
77
|
-
fields?: string | Array<string>;
|
|
78
|
-
/**
|
|
79
|
-
* Credentials of a superuser to get full access to the PocketBase instance.
|
|
80
|
-
* This is required to get automatic type generation without a local schema, to access all resources even if they are not public and to fetch content of hidden fields.
|
|
81
|
-
*/
|
|
82
|
-
superuserCredentials?:
|
|
83
|
-
| {
|
|
84
|
-
/**
|
|
85
|
-
* Email of the superuser.
|
|
86
|
-
*/
|
|
87
|
-
email: string;
|
|
88
|
-
/**
|
|
89
|
-
* Password of the superuser.
|
|
90
|
-
*/
|
|
91
|
-
password: string;
|
|
92
|
-
}
|
|
93
|
-
| {
|
|
94
|
-
/**
|
|
95
|
-
* Impersonate auth token of the superuser.
|
|
96
|
-
* This token will take precedence over the email and password.
|
|
97
|
-
*/
|
|
98
|
-
impersonateToken: string;
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Options for the PocketBase loader.
|
|
104
|
-
*/
|
|
105
|
-
export type PocketBaseLoaderOptions = PocketBaseLoaderBaseOptions & {
|
|
106
|
-
/**
|
|
107
|
-
* Field that should be used as the unique identifier for the collection.
|
|
108
|
-
* This must be the name of a field in the collection that contains unique values.
|
|
109
|
-
* If not provided, the `id` field will be used.
|
|
110
|
-
* The value of this field will be used in `getEntry` and `getEntries` to load the entry or entries.
|
|
111
|
-
*
|
|
112
|
-
* If the field is a string, it will be slugified to be used in the URL.
|
|
113
|
-
*/
|
|
114
|
-
idField?: string;
|
|
115
|
-
/**
|
|
116
|
-
* File path to the local schema file.
|
|
117
|
-
* This file will be used to generate the schema for the collection.
|
|
118
|
-
* If `superuserCredentials` are provided, this option will be ignored.
|
|
119
|
-
*/
|
|
120
|
-
localSchema?: string;
|
|
121
|
-
/**
|
|
122
|
-
* Record of zod schemas for all JSON fields in the collection.
|
|
123
|
-
* The key must be the name of a field in the collection.
|
|
124
|
-
* If no schema is provided for a field, the value will be treated as `unknown`.
|
|
125
|
-
*
|
|
126
|
-
* Note that this will only be used for fields of type `json`.
|
|
127
|
-
*/
|
|
128
|
-
jsonSchemas?: Record<string, ZodType>;
|
|
129
|
-
/**
|
|
130
|
-
* Experimental options for the loader.
|
|
131
|
-
*
|
|
132
|
-
* @experimental All of these options are experimental and may change in the future.
|
|
133
|
-
*/
|
|
134
|
-
experimental?: {
|
|
135
|
-
/**
|
|
136
|
-
* Whether to only create types for the live loader.
|
|
137
|
-
* This will not load any data, but only generate types that can be used with the live loader.
|
|
138
|
-
*/
|
|
139
|
-
liveTypesOnly?: boolean;
|
|
140
|
-
};
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Options for the PocketBase live loader.
|
|
145
|
-
*/
|
|
146
|
-
export type PocketBaseLiveLoaderOptions = PocketBaseLoaderBaseOptions;
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { z } from "astro/zod";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Entry for a collections schema in PocketBase.
|
|
5
|
-
*/
|
|
6
|
-
export const pocketBaseSchemaEntry = z.object({
|
|
7
|
-
/**
|
|
8
|
-
* Flag to indicate if the field is hidden.
|
|
9
|
-
* Hidden fields are not returned in the API response.
|
|
10
|
-
*/
|
|
11
|
-
hidden: z.optional(z.boolean()),
|
|
12
|
-
/**
|
|
13
|
-
* Unique identifier for the field.
|
|
14
|
-
*/
|
|
15
|
-
id: z.string(),
|
|
16
|
-
/**
|
|
17
|
-
* Name of the field.
|
|
18
|
-
*/
|
|
19
|
-
name: z.string(),
|
|
20
|
-
/**
|
|
21
|
-
* Help text for the field.
|
|
22
|
-
* This is only present if the field has help text defined.
|
|
23
|
-
*/
|
|
24
|
-
help: z.optional(z.string()),
|
|
25
|
-
/**
|
|
26
|
-
* Type of the field.
|
|
27
|
-
*/
|
|
28
|
-
type: z.enum([
|
|
29
|
-
"text",
|
|
30
|
-
"editor",
|
|
31
|
-
"number",
|
|
32
|
-
"bool",
|
|
33
|
-
"email",
|
|
34
|
-
"url",
|
|
35
|
-
"date",
|
|
36
|
-
"autodate",
|
|
37
|
-
"select",
|
|
38
|
-
"file",
|
|
39
|
-
"relation",
|
|
40
|
-
"json",
|
|
41
|
-
"geoPoint",
|
|
42
|
-
"password"
|
|
43
|
-
]),
|
|
44
|
-
/**
|
|
45
|
-
* Whether the field is required.
|
|
46
|
-
*/
|
|
47
|
-
required: z.optional(z.boolean()),
|
|
48
|
-
/**
|
|
49
|
-
* Values for a select field.
|
|
50
|
-
* This is only present if the field type is "select".
|
|
51
|
-
*/
|
|
52
|
-
values: z.optional(z.array(z.string())),
|
|
53
|
-
/**
|
|
54
|
-
* Maximum number of values for a select field.
|
|
55
|
-
* This is only present on "select", "relation", and "file" fields.
|
|
56
|
-
*/
|
|
57
|
-
maxSelect: z.optional(z.number()),
|
|
58
|
-
/**
|
|
59
|
-
* Whether the field is filled when the entry is created.
|
|
60
|
-
* This is only present on "autodate" fields.
|
|
61
|
-
*/
|
|
62
|
-
onCreate: z.optional(z.boolean()),
|
|
63
|
-
/**
|
|
64
|
-
* Whether the field is updated when the entry is updated.
|
|
65
|
-
* This is only present on "autodate" fields.
|
|
66
|
-
*/
|
|
67
|
-
onUpdate: z.optional(z.boolean())
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Entry for a collections schema in PocketBase.
|
|
72
|
-
*/
|
|
73
|
-
export type PocketBaseSchemaEntry = z.infer<typeof pocketBaseSchemaEntry>;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Schema for a PocketBase collection.
|
|
77
|
-
*/
|
|
78
|
-
export const pocketBaseCollection = z.object({
|
|
79
|
-
/**
|
|
80
|
-
* Name of the collection.
|
|
81
|
-
*/
|
|
82
|
-
name: z.string(),
|
|
83
|
-
/**
|
|
84
|
-
* Type of the collection.
|
|
85
|
-
*/
|
|
86
|
-
type: z.enum(["base", "view", "auth"]),
|
|
87
|
-
/**
|
|
88
|
-
* Schema of the collection.
|
|
89
|
-
*/
|
|
90
|
-
fields: z.array(pocketBaseSchemaEntry)
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Type for a PocketBase collection.
|
|
95
|
-
*/
|
|
96
|
-
export type PocketBaseCollection = z.infer<typeof pocketBaseCollection>;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Schema for an entire PocketBase database.
|
|
100
|
-
*/
|
|
101
|
-
export const pocketBaseDatabase = z.array(pocketBaseCollection);
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
PocketBaseLoaderBaseOptions,
|
|
3
|
-
PocketBaseLoaderOptions
|
|
4
|
-
} from "../types/pocketbase-loader-options.type";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Combine basic, special, and user-specified fields for PocketBase API requests.
|
|
8
|
-
* This utility ensures that required system fields are always included in API requests.
|
|
9
|
-
*
|
|
10
|
-
* @param userFields Array of fields specified by the user, or undefined for all fields
|
|
11
|
-
* @param options PocketBase loader options containing custom field configurations
|
|
12
|
-
* @returns Combined array of fields to include in the API request, or undefined for all fields
|
|
13
|
-
*/
|
|
14
|
-
export function combineFieldsForRequest(
|
|
15
|
-
userFields: Array<string> | undefined,
|
|
16
|
-
options: Pick<PocketBaseLoaderBaseOptions, "updatedField" | "contentFields"> &
|
|
17
|
-
Pick<PocketBaseLoaderOptions, "idField">
|
|
18
|
-
): Array<string> | undefined {
|
|
19
|
-
// If no fields specified, return undefined to get all fields
|
|
20
|
-
if (!userFields) {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Basic fields that are always required by the loader
|
|
25
|
-
const basicFields = ["id", "collectionId", "collectionName"];
|
|
26
|
-
|
|
27
|
-
// Special fields that are configured in options
|
|
28
|
-
const specialFields: Array<string> = [];
|
|
29
|
-
|
|
30
|
-
// Add custom id field if specified
|
|
31
|
-
if (options.idField && options.idField !== "id") {
|
|
32
|
-
specialFields.push(options.idField);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Add updated field if specified
|
|
36
|
-
if (options.updatedField) {
|
|
37
|
-
specialFields.push(options.updatedField);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Add content fields if specified
|
|
41
|
-
if (options.contentFields) {
|
|
42
|
-
if (Array.isArray(options.contentFields)) {
|
|
43
|
-
specialFields.push(...options.contentFields);
|
|
44
|
-
} else {
|
|
45
|
-
specialFields.push(options.contentFields);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Combine all field sets, removing duplicates
|
|
50
|
-
const allFields = [
|
|
51
|
-
...new Set([...basicFields, ...specialFields, ...userFields])
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
return allFields;
|
|
55
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { PocketBaseLoaderBaseOptions } from "../types/pocketbase-loader-options.type";
|
|
2
|
-
import { getSuperuserToken } from "./get-superuser-token";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a promise that resolves to a superuser token or undefined.
|
|
6
|
-
*/
|
|
7
|
-
export async function createTokenPromise(
|
|
8
|
-
options: Pick<PocketBaseLoaderBaseOptions, "superuserCredentials" | "url">
|
|
9
|
-
): Promise<string | undefined> {
|
|
10
|
-
if (options.superuserCredentials) {
|
|
11
|
-
if ("impersonateToken" in options.superuserCredentials) {
|
|
12
|
-
// Impersonate token provided, so use it directly.
|
|
13
|
-
return options.superuserCredentials.impersonateToken;
|
|
14
|
-
}
|
|
15
|
-
// Email and password provided, so get a temporary superuser token.
|
|
16
|
-
const token = await getSuperuserToken(
|
|
17
|
-
options.url,
|
|
18
|
-
options.superuserCredentials
|
|
19
|
-
);
|
|
20
|
-
return token;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// No credentials provided, so no token can be used.
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract field names from fields that may contain modifiers like :excerpt().
|
|
3
|
-
*
|
|
4
|
-
* @param fields Array of field specifications that may contain modifiers
|
|
5
|
-
* @returns Array of clean field names suitable for schema parsing
|
|
6
|
-
*/
|
|
7
|
-
export function extractFieldNames(
|
|
8
|
-
fields: Array<string> | undefined
|
|
9
|
-
): Array<string> | undefined {
|
|
10
|
-
if (!fields) {
|
|
11
|
-
return undefined;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return fields.map((field) => field.split(":").at(0) ?? field);
|
|
15
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import type { PocketBaseLoaderBaseOptions } from "../types/pocketbase-loader-options.type";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Format fields option into an array and validate for expand usage.
|
|
5
|
-
* Handles wildcard "*" and preserves excerpt field modifiers.
|
|
6
|
-
*
|
|
7
|
-
* @param fields The fields option (string or array)
|
|
8
|
-
* @returns Formatted fields array, or undefined if no fields specified or "*" wildcard is used
|
|
9
|
-
*/
|
|
10
|
-
export function formatFields(
|
|
11
|
-
fields: PocketBaseLoaderBaseOptions["fields"]
|
|
12
|
-
): Array<string> | undefined {
|
|
13
|
-
if (!fields || fields.length === 0) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let fieldList: Array<string>;
|
|
18
|
-
if (Array.isArray(fields)) {
|
|
19
|
-
fieldList = fields.map((f) => f.trim());
|
|
20
|
-
} else {
|
|
21
|
-
// Split carefully, respecting parentheses in excerpt syntax
|
|
22
|
-
fieldList = splitFieldsString(fields).map((f) => f.trim());
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Warn if expand is used since it's not currently supported
|
|
26
|
-
const hasExpand = fieldList.some((field) => field.includes("expand"));
|
|
27
|
-
if (hasExpand) {
|
|
28
|
-
console.warn(
|
|
29
|
-
'The "expand" parameter is not currently supported by astro-loader-pocketbase and will be filtered out.'
|
|
30
|
-
);
|
|
31
|
-
fieldList = fieldList.filter((field) => !field.includes("expand"));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Check for "*" wildcard - if found anywhere, include all fields
|
|
35
|
-
const hasWildcard = fieldList.some((field) => field === "*");
|
|
36
|
-
if (hasWildcard) {
|
|
37
|
-
return undefined;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return fieldList;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Splits the fields string at `,` but respects the `:excerpt(number, boolean)` option
|
|
45
|
-
*/
|
|
46
|
-
function splitFieldsString(fieldsString: string): Array<string> {
|
|
47
|
-
// First, split by comma
|
|
48
|
-
const initialSplit = fieldsString.split(",");
|
|
49
|
-
|
|
50
|
-
const fields: Array<string> = [];
|
|
51
|
-
for (let i = 0; i < initialSplit.length; i++) {
|
|
52
|
-
const part = initialSplit.at(i);
|
|
53
|
-
if (!part) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (part.includes("(") && !part.includes(")")) {
|
|
58
|
-
fields.push(`${part},${initialSplit[++i]}`);
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
fields.push(part);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return fields;
|
|
66
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { AstroIntegrationLogger } from "astro";
|
|
2
|
-
import {
|
|
3
|
-
pocketBaseErrorResponse,
|
|
4
|
-
pocketBaseLoginResponse
|
|
5
|
-
} from "../types/pocketbase-api-response.type";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* This function will get a superuser token from the given PocketBase instance.
|
|
9
|
-
*
|
|
10
|
-
* @param url URL of the PocketBase instance
|
|
11
|
-
* @param superuserCredentials Credentials of the superuser
|
|
12
|
-
*
|
|
13
|
-
* @returns A superuser token to access all resources of the PocketBase instance.
|
|
14
|
-
*/
|
|
15
|
-
export async function getSuperuserToken(
|
|
16
|
-
url: string,
|
|
17
|
-
superuserCredentials: {
|
|
18
|
-
email: string;
|
|
19
|
-
password: string;
|
|
20
|
-
},
|
|
21
|
-
logger?: AstroIntegrationLogger
|
|
22
|
-
): Promise<string | undefined> {
|
|
23
|
-
// Build the URL for the login endpoint
|
|
24
|
-
const loginUrl = new URL(
|
|
25
|
-
`api/collections/_superusers/auth-with-password`,
|
|
26
|
-
url
|
|
27
|
-
).href;
|
|
28
|
-
|
|
29
|
-
// Create a new FormData object to send the login data
|
|
30
|
-
const loginData = new FormData();
|
|
31
|
-
loginData.set("identity", superuserCredentials.email);
|
|
32
|
-
loginData.set("password", superuserCredentials.password);
|
|
33
|
-
|
|
34
|
-
// Send the login request to get a token
|
|
35
|
-
const loginRequest = await fetch(loginUrl, {
|
|
36
|
-
method: "POST",
|
|
37
|
-
body: loginData
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// If the login request was not successful, print the error message and return undefined
|
|
41
|
-
if (!loginRequest.ok) {
|
|
42
|
-
if (loginRequest.status === 429) {
|
|
43
|
-
const info =
|
|
44
|
-
"A rate limit was hit while trying to authenticate with PocketBase. Consider using an `impersonateToken` as credentials to avoid this issue.";
|
|
45
|
-
if (logger) {
|
|
46
|
-
logger.info(info);
|
|
47
|
-
} else {
|
|
48
|
-
console.info(info);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Random wait between 3 (default rate limit interval) and 8 seconds
|
|
52
|
-
const retryAfter = Math.random() * 5 + 3;
|
|
53
|
-
// oxlint-disable-next-line promise/avoid-new
|
|
54
|
-
await new Promise((resolve) => {
|
|
55
|
-
setTimeout(resolve, retryAfter * 1000);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return getSuperuserToken(url, superuserCredentials, logger);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const errorResponse = pocketBaseErrorResponse.parse(
|
|
62
|
-
await loginRequest.json()
|
|
63
|
-
);
|
|
64
|
-
const errorMessage = `The given email / password for ${url} was not correct. Astro can't generate type definitions automatically and may not have access to all resources.\nReason: ${errorResponse.message}`;
|
|
65
|
-
if (logger) {
|
|
66
|
-
logger.error(errorMessage);
|
|
67
|
-
} else {
|
|
68
|
-
console.error(errorMessage);
|
|
69
|
-
}
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Return the token
|
|
74
|
-
const response = pocketBaseLoginResponse.parse(await loginRequest.json());
|
|
75
|
-
return response.token;
|
|
76
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { z } from "astro/zod";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Schema for realtime data received from PocketBase.
|
|
5
|
-
*/
|
|
6
|
-
const realtimeDataSchema = z.object({
|
|
7
|
-
action: z.union([
|
|
8
|
-
z.literal("create"),
|
|
9
|
-
z.literal("update"),
|
|
10
|
-
z.literal("delete")
|
|
11
|
-
]),
|
|
12
|
-
record: z.object({
|
|
13
|
-
id: z.string(),
|
|
14
|
-
collectionName: z.string(),
|
|
15
|
-
collectionId: z.string()
|
|
16
|
-
})
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Type for realtime data received from PocketBase.
|
|
21
|
-
*/
|
|
22
|
-
export type RealtimeData = z.infer<typeof realtimeDataSchema>;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Checks if the given data is realtime data received from PocketBase.
|
|
26
|
-
*/
|
|
27
|
-
export function isRealtimeData(data: unknown): data is RealtimeData {
|
|
28
|
-
try {
|
|
29
|
-
realtimeDataSchema.parse(data);
|
|
30
|
-
return true;
|
|
31
|
-
} catch {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { LoaderContext } from "astro/loaders";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Checks if the collection should be refreshed.
|
|
5
|
-
*/
|
|
6
|
-
export function shouldRefresh(
|
|
7
|
-
context: LoaderContext["refreshContextData"],
|
|
8
|
-
collectionName: string
|
|
9
|
-
): "refresh" | "skip" | "force" {
|
|
10
|
-
// Check if the refresh was triggered by the `astro-integration-pocketbase`
|
|
11
|
-
// and the correct metadata is provided.
|
|
12
|
-
if (context?.source !== "astro-integration-pocketbase") {
|
|
13
|
-
return "refresh";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Check if all collections should be refreshed.
|
|
17
|
-
if (context.force) {
|
|
18
|
-
return "force";
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!context.collection) {
|
|
22
|
-
return "refresh";
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Check if the collection name matches the current collection.
|
|
26
|
-
if (typeof context.collection === "string") {
|
|
27
|
-
return context.collection === collectionName ? "refresh" : "skip";
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Check if the collection is included in the list of collections.
|
|
31
|
-
if (Array.isArray(context.collection)) {
|
|
32
|
-
return context.collection.includes(collectionName) ? "refresh" : "skip";
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Should not happen but return true to be safe.
|
|
36
|
-
return "refresh";
|
|
37
|
-
}
|
package/src/utils/slugify.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Convert a string to a slug.
|
|
3
|
-
*
|
|
4
|
-
* Example:
|
|
5
|
-
* ```ts
|
|
6
|
-
* slugify("Hello World!"); // hello-world
|
|
7
|
-
* ```
|
|
8
|
-
*/
|
|
9
|
-
export function slugify(input: string): string {
|
|
10
|
-
return input
|
|
11
|
-
.toLowerCase()
|
|
12
|
-
.replaceAll(/\s+/g, "-") // Replace spaces with -
|
|
13
|
-
.replaceAll("ä", "ae") // Replace umlauts
|
|
14
|
-
.replaceAll("ö", "oe")
|
|
15
|
-
.replaceAll("ü", "ue")
|
|
16
|
-
.replaceAll("ß", "ss")
|
|
17
|
-
.replaceAll(/[^\w-]+/g, "") // Remove all non-word chars
|
|
18
|
-
.replaceAll(/--+/g, "-") // Replace multiple - with single -
|
|
19
|
-
.replace(/^-+/, "") // Trim - from start of text
|
|
20
|
-
.replace(/-+$/, ""); // Trim - from end of text
|
|
21
|
-
}
|