astro-integration-pocketbase 3.1.1 → 3.1.2-next.2
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/{src/types/pocketbase-integration-options.type.ts → dist/index.d.mts} +26 -19
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +237 -0
- package/dist/index.mjs.map +1 -0
- package/dist/middleware.d.mts +5 -0
- package/dist/middleware.d.mts.map +1 -0
- package/dist/middleware.mjs +53 -0
- package/dist/middleware.mjs.map +1 -0
- package/dist/toolbar.d.mts +5 -0
- package/dist/toolbar.d.mts.map +1 -0
- package/dist/toolbar.mjs +254 -0
- package/dist/toolbar.mjs.map +1 -0
- package/package.json +23 -13
- package/index.ts +0 -5
- package/src/core/index.ts +0 -2
- package/src/core/refresh-collections-realtime.ts +0 -169
- package/src/core/refresh-collections.ts +0 -46
- package/src/middleware/index.ts +0 -50
- package/src/middleware/is-pocketbase-entry.ts +0 -33
- package/src/pocketbase-integration.ts +0 -75
- package/src/toolbar/dom/create-entity.ts +0 -69
- package/src/toolbar/dom/create-header.ts +0 -153
- package/src/toolbar/dom/create-placeholder.ts +0 -20
- package/src/toolbar/dom/index.ts +0 -3
- package/src/toolbar/index.ts +0 -6
- package/src/toolbar/init-toolbar.ts +0 -98
- package/src/toolbar/types/entity.ts +0 -8
- package/src/toolbar/types/options.ts +0 -17
- package/src/tsconfig.json +0 -7
- package/src/types/pocketbase-api-response.type.ts +0 -21
- package/src/utils/get-superuser-token.ts +0 -68
- package/src/utils/map-collections-to-watch.ts +0 -56
- package/src/utils/push-to-map-array.ts +0 -16
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
-
import type { AstroIntegration } from "astro";
|
|
3
|
-
import type { EventSource } from "eventsource";
|
|
4
|
-
import { handleRefreshCollections, refreshCollectionsRealtime } from "./core";
|
|
5
|
-
import type { ToolbarOptions } from "./toolbar/types/options";
|
|
6
|
-
import type { PocketBaseIntegrationOptions } from "./types/pocketbase-integration-options.type";
|
|
7
|
-
|
|
8
|
-
export function pocketbaseIntegration(
|
|
9
|
-
options: PocketBaseIntegrationOptions
|
|
10
|
-
): AstroIntegration {
|
|
11
|
-
let eventSource: EventSource | undefined = undefined;
|
|
12
|
-
let initialSetupDone = false;
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
name: "pocketbase-integration",
|
|
16
|
-
hooks: {
|
|
17
|
-
"astro:config:setup": ({
|
|
18
|
-
addDevToolbarApp,
|
|
19
|
-
addMiddleware,
|
|
20
|
-
command
|
|
21
|
-
}): void => {
|
|
22
|
-
// This integration is only available in dev mode
|
|
23
|
-
if (command !== "dev") {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Setup Toolbar
|
|
28
|
-
addDevToolbarApp({
|
|
29
|
-
name: "PocketBase",
|
|
30
|
-
id: `pocketbase-entry`,
|
|
31
|
-
icon: `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>PocketBase</title><path fill="currentColor" d="M5.684 12a.632.632 0 0 1-.631-.632V4.421c0-.349.282-.632.631-.632h2.37c.46 0 .889.047 1.287.139.407.084.758.23 1.053.44.303.202.541.475.715.82.173.335.26.75.26 1.246 0 .479-.092.894-.273 1.247a2.373 2.373 0 0 1-.715.869 3.11 3.11 0 0 1-1.053.503c-.398.11-.823.164-1.273.164h-.46a.632.632 0 0 0-.632.632v1.52a.632.632 0 0 1-.632.631Zm1.279-4.888c0 .349.283.632.632.632h.343c1.04 0 1.56-.437 1.56-1.31 0-.428-.135-.73-.404-.907-.26-.176-.645-.264-1.156-.264h-.343a.632.632 0 0 0-.632.631Zm6.3 13.098a.632.632 0 0 1-.631-.631v-6.947a.63.63 0 0 1 .631-.632h2.203c.44 0 .845.034 1.216.1.38.06.708.169.984.328.276.16.492.37.647.63.164.26.246.587.246.982 0 .185-.03.37-.09.554a1.537 1.537 0 0 1-.26.516 1.857 1.857 0 0 1-1.076.7.031.031 0 0 0-.023.03c0 .015.01.028.025.03.591.111 1.04.32 1.346.626.311.31.466.743.466 1.297 0 .42-.082.78-.246 1.083a2.153 2.153 0 0 1-.685.755 3.4 3.4 0 0 1-1.036.441 5.477 5.477 0 0 1-1.268.139zm1.271-5.542c0 .349.283.631.632.631h.21c.465 0 .802-.088 1.009-.264.207-.176.31-.424.31-.743 0-.302-.107-.516-.323-.642-.207-.135-.535-.202-.984-.202h-.222a.632.632 0 0 0-.632.632Zm0 3.463c0 .349.283.631.632.631h.39c1.019 0 1.528-.369 1.528-1.108 0-.36-.125-.621-.376-.78-.241-.16-.625-.24-1.152-.24h-.39a.632.632 0 0 0-.632.632zM1.389 0C.629 0 0 .629 0 1.389V15.03a1.4 1.4 0 0 0 1.389 1.39H8.21a.632.632 0 0 0 .63-.632.632.632 0 0 0-.63-.63H1.389c-.078 0-.125-.05-.125-.128V1.39c0-.078.047-.125.125-.125H15.03c.078 0 .127.047.127.125v6.82a.632.632 0 0 0 .631.63.632.632 0 0 0 .633-.63V1.389A1.4 1.4 0 0 0 15.032 0ZM15.79 7.578a.632.632 0 0 0-.632.633.632.632 0 0 0 .631.63h6.822c.078 0 .125.05.125.128V22.61c0 .078-.047.125-.125.125H8.97c-.077 0-.127-.047-.127-.125v-6.82a.632.632 0 0 0-.631-.63.632.632 0 0 0-.633.63v6.822A1.4 1.4 0 0 0 8.968 24h13.643c.76 0 1.389-.629 1.389-1.389V8.97a1.4 1.4 0 0 0-1.389-1.39Z"/></svg>`,
|
|
32
|
-
entrypoint: fileURLToPath(new URL("./toolbar", import.meta.url))
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Setup middleware
|
|
36
|
-
addMiddleware({
|
|
37
|
-
order: "post",
|
|
38
|
-
entrypoint: fileURLToPath(new URL("./middleware", import.meta.url))
|
|
39
|
-
});
|
|
40
|
-
},
|
|
41
|
-
"astro:server:setup": (setupOptions): void => {
|
|
42
|
-
if (!initialSetupDone) {
|
|
43
|
-
// Listen for the refresh event of the toolbar
|
|
44
|
-
handleRefreshCollections(setupOptions);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Subscribe to PocketBase realtime API
|
|
48
|
-
if (eventSource) {
|
|
49
|
-
eventSource.close();
|
|
50
|
-
eventSource = undefined;
|
|
51
|
-
}
|
|
52
|
-
eventSource = refreshCollectionsRealtime(options, setupOptions);
|
|
53
|
-
|
|
54
|
-
// Send settings to the toolbar on initialization
|
|
55
|
-
setupOptions.toolbar.onAppInitialized("pocketbase-entry", () => {
|
|
56
|
-
setupOptions.toolbar.send("astro-integration-pocketbase:settings", {
|
|
57
|
-
hasContentLoader: !!setupOptions.refreshContent,
|
|
58
|
-
realtime: !!eventSource,
|
|
59
|
-
baseUrl: options.url
|
|
60
|
-
} satisfies ToolbarOptions);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
initialSetupDone = true;
|
|
64
|
-
},
|
|
65
|
-
"astro:server:done": ({ logger }): void => {
|
|
66
|
-
// Close the EventSource connection when the server is done
|
|
67
|
-
if (eventSource) {
|
|
68
|
-
logger.info("Closing EventSource connection");
|
|
69
|
-
eventSource.close();
|
|
70
|
-
eventSource = undefined;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { Entity } from "../types/entity";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates cards for the entities.
|
|
5
|
-
*/
|
|
6
|
-
export function createEntities(data: Array<Entity>, baseUrl: string): string {
|
|
7
|
-
const groupedData = Object.groupBy(data, (data) => data.collectionName);
|
|
8
|
-
const collections = Object.keys(groupedData);
|
|
9
|
-
|
|
10
|
-
return /* HTML */ `
|
|
11
|
-
<style>
|
|
12
|
-
.collectionName {
|
|
13
|
-
text-transform: capitalize;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.entity {
|
|
17
|
-
position: relative;
|
|
18
|
-
|
|
19
|
-
pre {
|
|
20
|
-
margin: 0;
|
|
21
|
-
overflow: auto;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
astro-dev-toolbar-button {
|
|
25
|
-
position: absolute;
|
|
26
|
-
top: 0;
|
|
27
|
-
right: 0;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
</style>
|
|
31
|
-
|
|
32
|
-
${collections
|
|
33
|
-
.map(
|
|
34
|
-
(collection) => /* HTML */ `
|
|
35
|
-
<b class=".collectionName">${collection}</b>
|
|
36
|
-
${groupedData[collection]
|
|
37
|
-
?.map((entity) => createEntity(entity, baseUrl))
|
|
38
|
-
.join("")}
|
|
39
|
-
`
|
|
40
|
-
)
|
|
41
|
-
.join("")}
|
|
42
|
-
`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Creates a card for a single entity
|
|
47
|
-
*/
|
|
48
|
-
function createEntity(data: Entity, baseUrl: string): string {
|
|
49
|
-
return /* HTML */ `
|
|
50
|
-
<astro-dev-toolbar-card>
|
|
51
|
-
<div class="entity">
|
|
52
|
-
<pre>${JSON.stringify(data, undefined, 2).replaceAll("<", "<")}</pre>
|
|
53
|
-
|
|
54
|
-
${baseUrl
|
|
55
|
-
? /* HTML */ `
|
|
56
|
-
<astro-dev-toolbar-button
|
|
57
|
-
size="small"
|
|
58
|
-
button-style="purple"
|
|
59
|
-
title="View in PocketBase"
|
|
60
|
-
onclick="window.open('${baseUrl}/_/#/collections?collection=${data.collectionId}&recordId=${data.id}&record=${data.id}', '_blank')"
|
|
61
|
-
>
|
|
62
|
-
View in PocketBase
|
|
63
|
-
</astro-dev-toolbar-button>
|
|
64
|
-
`
|
|
65
|
-
: ""}
|
|
66
|
-
</div>
|
|
67
|
-
</astro-dev-toolbar-card>
|
|
68
|
-
`;
|
|
69
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import type { ToolbarServerHelpers } from "astro";
|
|
2
|
-
import type { DevToolbarButton } from "astro/runtime/client/dev-toolbar/ui-library/button.js";
|
|
3
|
-
import type { DevToolbarWindow } from "astro/runtime/client/dev-toolbar/ui-library/window.js";
|
|
4
|
-
import { default as packageJson } from "../../../package.json";
|
|
5
|
-
import type { ToolbarOptions } from "../types/options";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Creates the header for the PocketBase toolbar.
|
|
9
|
-
*/
|
|
10
|
-
// oxlint-disable-next-line max-lines-per-function
|
|
11
|
-
export function createHeader(
|
|
12
|
-
windowElement: DevToolbarWindow,
|
|
13
|
-
server: ToolbarServerHelpers,
|
|
14
|
-
{ hasContentLoader, realtime }: ToolbarOptions
|
|
15
|
-
): void {
|
|
16
|
-
const header = windowElement.querySelector("header");
|
|
17
|
-
if (!header) {
|
|
18
|
-
throw new Error("The header element is missing");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
header.innerHTML = /* HTML */ `
|
|
22
|
-
<style>
|
|
23
|
-
header {
|
|
24
|
-
display: grid;
|
|
25
|
-
grid-template-columns: auto auto 1fr;
|
|
26
|
-
gap: 0.5rem;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
h1 {
|
|
30
|
-
display: flex;
|
|
31
|
-
align-items: center;
|
|
32
|
-
gap: 8px;
|
|
33
|
-
font-weight: 600;
|
|
34
|
-
color: #fff;
|
|
35
|
-
margin: 0;
|
|
36
|
-
font-size: 22px;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.actions {
|
|
40
|
-
display: flex;
|
|
41
|
-
align-items: start;
|
|
42
|
-
justify-content: flex-end;
|
|
43
|
-
gap: 0.25rem;
|
|
44
|
-
|
|
45
|
-
.toggle-container {
|
|
46
|
-
display: flex;
|
|
47
|
-
align-items: center;
|
|
48
|
-
|
|
49
|
-
label {
|
|
50
|
-
font-size: 0.8rem;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
</style>
|
|
55
|
-
|
|
56
|
-
<h1>PocketBase</h1>
|
|
57
|
-
<astro-dev-toolbar-badge badge-style="yellow">
|
|
58
|
-
${packageJson.version}
|
|
59
|
-
</astro-dev-toolbar-badge>
|
|
60
|
-
|
|
61
|
-
<div class="actions">
|
|
62
|
-
${realtime
|
|
63
|
-
? /* HTML */ `
|
|
64
|
-
<div class="toggle-container">
|
|
65
|
-
<label
|
|
66
|
-
for="real-time"
|
|
67
|
-
title="Enable or disable real-time updates temporarily"
|
|
68
|
-
>
|
|
69
|
-
Real-time updates
|
|
70
|
-
</label>
|
|
71
|
-
<!-- real-time-toggle -->
|
|
72
|
-
</div>
|
|
73
|
-
`
|
|
74
|
-
: ""}
|
|
75
|
-
${hasContentLoader
|
|
76
|
-
? /* HTML */ `
|
|
77
|
-
<astro-dev-toolbar-button
|
|
78
|
-
id="refresh-content"
|
|
79
|
-
size="small"
|
|
80
|
-
button-style="green"
|
|
81
|
-
title="Right click to force refresh every collection"
|
|
82
|
-
>
|
|
83
|
-
Refresh content
|
|
84
|
-
</astro-dev-toolbar-button>
|
|
85
|
-
`
|
|
86
|
-
: ""}
|
|
87
|
-
</div>
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
|
-
if (realtime) {
|
|
91
|
-
// Create the toggle for real-time updates
|
|
92
|
-
const realTimeToggle = document.createElement("astro-dev-toolbar-toggle");
|
|
93
|
-
realTimeToggle.input.id = "real-time-toggle";
|
|
94
|
-
realTimeToggle.input.title =
|
|
95
|
-
"Enable or disable real-time updates temporarily";
|
|
96
|
-
// Set the toggle state based on the local storage, default to true
|
|
97
|
-
realTimeToggle.input.checked = !(
|
|
98
|
-
localStorage.getItem("astro-integration-pocketbase:real-time") === "false"
|
|
99
|
-
);
|
|
100
|
-
realTimeToggle.input.addEventListener("change", () => {
|
|
101
|
-
// Store the toggle state in the local storage
|
|
102
|
-
localStorage.setItem(
|
|
103
|
-
"astro-integration-pocketbase:real-time",
|
|
104
|
-
realTimeToggle.input.checked.toString()
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
// Send the toggle state to the server
|
|
108
|
-
server.send(
|
|
109
|
-
"astro-integration-pocketbase:real-time",
|
|
110
|
-
realTimeToggle.input.checked
|
|
111
|
-
);
|
|
112
|
-
});
|
|
113
|
-
// Send the initial toggle state to the server
|
|
114
|
-
server.send(
|
|
115
|
-
"astro-integration-pocketbase:real-time",
|
|
116
|
-
realTimeToggle.input.checked
|
|
117
|
-
);
|
|
118
|
-
windowElement.querySelector(".toggle-container")?.append(realTimeToggle);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (hasContentLoader) {
|
|
122
|
-
// Add click listeners to the refresh button
|
|
123
|
-
const refresh =
|
|
124
|
-
windowElement.querySelector<DevToolbarButton>("#refresh-content");
|
|
125
|
-
if (!refresh) {
|
|
126
|
-
throw new Error("The refresh button is missing");
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
refresh.addEventListener("click", () => {
|
|
130
|
-
server.send("astro-integration-pocketbase:refresh", { force: false });
|
|
131
|
-
});
|
|
132
|
-
refresh.addEventListener("contextmenu", (event) => {
|
|
133
|
-
event.preventDefault();
|
|
134
|
-
server.send("astro-integration-pocketbase:refresh", { force: true });
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
server.on(
|
|
138
|
-
"astro-integration-pocketbase:refresh",
|
|
139
|
-
({ loading }: { loading?: boolean }) => {
|
|
140
|
-
// Show loading state while refreshing content
|
|
141
|
-
if (loading) {
|
|
142
|
-
refresh.textContent = "Refreshing content...";
|
|
143
|
-
refresh.buttonStyle = "gray";
|
|
144
|
-
refresh.style.pointerEvents = "none";
|
|
145
|
-
} else {
|
|
146
|
-
refresh.textContent = "Refresh content";
|
|
147
|
-
refresh.buttonStyle = "green";
|
|
148
|
-
refresh.style.pointerEvents = "unset";
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a placeholder card.
|
|
3
|
-
*/
|
|
4
|
-
export function createPlaceholder(): string {
|
|
5
|
-
return /* HTML */ `
|
|
6
|
-
<style>
|
|
7
|
-
#placeholder div {
|
|
8
|
-
display: flex;
|
|
9
|
-
align-items: center;
|
|
10
|
-
justify-content: center;
|
|
11
|
-
}
|
|
12
|
-
</style>
|
|
13
|
-
|
|
14
|
-
<astro-dev-toolbar-card id="placeholder">
|
|
15
|
-
<div>
|
|
16
|
-
<span> Here you will see the raw content of an entity </span>
|
|
17
|
-
</div>
|
|
18
|
-
</astro-dev-toolbar-card>
|
|
19
|
-
`;
|
|
20
|
-
}
|
package/src/toolbar/dom/index.ts
DELETED
package/src/toolbar/index.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
closeOnOutsideClick,
|
|
3
|
-
createWindowElement,
|
|
4
|
-
synchronizePlacementOnUpdate
|
|
5
|
-
} from "astro/runtime/client/dev-toolbar/apps/utils/window.js";
|
|
6
|
-
import type {
|
|
7
|
-
ToolbarAppEventTarget,
|
|
8
|
-
ToolbarServerHelpers
|
|
9
|
-
} from "astro/runtime/client/dev-toolbar/helpers.js";
|
|
10
|
-
import { createEntities, createHeader, createPlaceholder } from "./dom";
|
|
11
|
-
import type { Entity } from "./types/entity";
|
|
12
|
-
import type { ToolbarOptions } from "./types/options";
|
|
13
|
-
|
|
14
|
-
declare global {
|
|
15
|
-
interface Window {
|
|
16
|
-
__astro_entities__?: Array<Entity>;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Initializes the PocketBase toolbar.
|
|
22
|
-
*/
|
|
23
|
-
export function initToolbar(
|
|
24
|
-
canvas: ShadowRoot,
|
|
25
|
-
app: ToolbarAppEventTarget,
|
|
26
|
-
server: ToolbarServerHelpers
|
|
27
|
-
): void {
|
|
28
|
-
// Options for the toolbar
|
|
29
|
-
let options: ToolbarOptions = {
|
|
30
|
-
realtime: false,
|
|
31
|
-
hasContentLoader: false,
|
|
32
|
-
baseUrl: ""
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// Update the options and refresh the toolbar
|
|
36
|
-
server.on(
|
|
37
|
-
"astro-integration-pocketbase:settings",
|
|
38
|
-
(updatedOptions: ToolbarOptions) => {
|
|
39
|
-
options = updatedOptions;
|
|
40
|
-
createPocketBaseWindow();
|
|
41
|
-
}
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
// Create the window (for every page navigation)
|
|
45
|
-
createPocketBaseWindow();
|
|
46
|
-
document.addEventListener("astro:after-swap", createPocketBaseWindow);
|
|
47
|
-
|
|
48
|
-
// Setup the window
|
|
49
|
-
closeOnOutsideClick(app);
|
|
50
|
-
synchronizePlacementOnUpdate(app, canvas);
|
|
51
|
-
|
|
52
|
-
function createPocketBaseWindow(): void {
|
|
53
|
-
// Clear any existing content
|
|
54
|
-
canvas.innerHTML = "";
|
|
55
|
-
|
|
56
|
-
const entities = window.__astro_entities__ || [];
|
|
57
|
-
|
|
58
|
-
// Create the main window element
|
|
59
|
-
const windowElement = createWindowElement(/* HTML */ `
|
|
60
|
-
<style>
|
|
61
|
-
:host astro-dev-toolbar-window {
|
|
62
|
-
max-height: 480px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
main {
|
|
66
|
-
display: flex;
|
|
67
|
-
flex-direction: column;
|
|
68
|
-
gap: 1rem;
|
|
69
|
-
overflow-y: auto;
|
|
70
|
-
}
|
|
71
|
-
</style>
|
|
72
|
-
|
|
73
|
-
<header></header>
|
|
74
|
-
|
|
75
|
-
<hr />
|
|
76
|
-
|
|
77
|
-
<main>
|
|
78
|
-
${entities.length > 0
|
|
79
|
-
? createEntities(entities, options.baseUrl)
|
|
80
|
-
: createPlaceholder()}
|
|
81
|
-
</main>
|
|
82
|
-
`);
|
|
83
|
-
|
|
84
|
-
// Create and insert the header
|
|
85
|
-
createHeader(windowElement, server, options);
|
|
86
|
-
|
|
87
|
-
// Add the window to the canvas
|
|
88
|
-
canvas.append(windowElement);
|
|
89
|
-
|
|
90
|
-
// Update the toolbar depending on the current state
|
|
91
|
-
if (entities.length > 0) {
|
|
92
|
-
app.toggleNotification({ state: true, level: "info" });
|
|
93
|
-
} else {
|
|
94
|
-
app.toggleNotification({ state: false });
|
|
95
|
-
app.toggleState({ state: false });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Options for the toolbar.
|
|
3
|
-
*/
|
|
4
|
-
export interface ToolbarOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Whether a content loader is active.
|
|
7
|
-
*/
|
|
8
|
-
hasContentLoader: boolean;
|
|
9
|
-
/**
|
|
10
|
-
* Whether a realtime connection to PocketBase is active.
|
|
11
|
-
*/
|
|
12
|
-
realtime: boolean;
|
|
13
|
-
/**
|
|
14
|
-
* Base URL of the PocketBase instance.
|
|
15
|
-
*/
|
|
16
|
-
baseUrl: string;
|
|
17
|
-
}
|
package/src/tsconfig.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { z } from "astro/zod";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The schema for a PocketBase error response.
|
|
5
|
-
*/
|
|
6
|
-
export const pocketBaseErrorResponse = z.object({
|
|
7
|
-
/**
|
|
8
|
-
* The error message returned by PocketBase.
|
|
9
|
-
*/
|
|
10
|
-
message: z.string()
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The schema for a PocketBase login response.
|
|
15
|
-
*/
|
|
16
|
-
export const pocketBaseLoginResponse = z.object({
|
|
17
|
-
/**
|
|
18
|
-
* The authentication token returned by PocketBase.
|
|
19
|
-
*/
|
|
20
|
-
token: z.string()
|
|
21
|
-
});
|
|
@@ -1,68 +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
|
-
logger.info(info);
|
|
46
|
-
|
|
47
|
-
// Random wait between 3 (default rate limit interval) and 8 seconds
|
|
48
|
-
const retryAfter = Math.random() * 5 + 3;
|
|
49
|
-
// oxlint-disable-next-line promise/avoid-new
|
|
50
|
-
await new Promise((resolve) => {
|
|
51
|
-
setTimeout(resolve, retryAfter * 1000);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return getSuperuserToken(url, superuserCredentials, logger);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const errorResponse = pocketBaseErrorResponse.parse(
|
|
58
|
-
await loginRequest.json()
|
|
59
|
-
);
|
|
60
|
-
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}`;
|
|
61
|
-
logger.error(errorMessage);
|
|
62
|
-
return undefined;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Return the token
|
|
66
|
-
const response = pocketBaseLoginResponse.parse(await loginRequest.json());
|
|
67
|
-
return response.token;
|
|
68
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type { PocketBaseIntegrationOptions } from "../types/pocketbase-integration-options.type";
|
|
2
|
-
import { pushToMapArray } from "./push-to-map-array";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Create a map of remote collections to watch.
|
|
6
|
-
* Each key in the map represents a remote collection to subscribe to.
|
|
7
|
-
* The value is an array of local collections that should be refreshed when an entry in the remote collection changes.
|
|
8
|
-
*/
|
|
9
|
-
export function mapCollectionsToWatch(
|
|
10
|
-
collectionsToWatch: PocketBaseIntegrationOptions["collectionsToWatch"]
|
|
11
|
-
): Map<string, Array<string>> | undefined {
|
|
12
|
-
// Check if collections should be watched
|
|
13
|
-
if (!collectionsToWatch) {
|
|
14
|
-
return undefined;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Check if collectionsToWatch is an array
|
|
18
|
-
if (Array.isArray(collectionsToWatch)) {
|
|
19
|
-
// Check if the array is empty
|
|
20
|
-
if (collectionsToWatch.length === 0) {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Create a map where each collection is watched by itself
|
|
25
|
-
return new Map(
|
|
26
|
-
collectionsToWatch.map((collection) => [collection, [collection]])
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Check if collectionsToWatch is an empty object
|
|
31
|
-
if (Object.keys(collectionsToWatch).length === 0) {
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Map collections to watch
|
|
36
|
-
const collectionsMap = new Map<string, Array<string>>();
|
|
37
|
-
for (const localCollection in collectionsToWatch) {
|
|
38
|
-
const watch = collectionsToWatch[localCollection];
|
|
39
|
-
if (!watch) {
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Check if collection should be watched by itself
|
|
44
|
-
if (watch === true) {
|
|
45
|
-
pushToMapArray(collectionsMap, localCollection, localCollection);
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Collection should be watched by multiple collections
|
|
50
|
-
for (const remoteCollection of watch) {
|
|
51
|
-
pushToMapArray(collectionsMap, remoteCollection, localCollection);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return collectionsMap;
|
|
56
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adds a value to an array in a map. If the key does not exist, it will be created.
|
|
3
|
-
*/
|
|
4
|
-
export function pushToMapArray<TKey, TArray>(
|
|
5
|
-
map: Map<TKey, Array<TArray>>,
|
|
6
|
-
key: TKey,
|
|
7
|
-
value: TArray
|
|
8
|
-
): void {
|
|
9
|
-
const array = map.get(key);
|
|
10
|
-
if (array) {
|
|
11
|
-
array.push(value);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
map.set(key, [value]);
|
|
16
|
-
}
|