@protobase/server 0.23.6 → 0.23.8
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/check-views.js
CHANGED
|
@@ -7,7 +7,7 @@ import { mapDisplayErrors, mapErrors } from "./view-map.js";
|
|
|
7
7
|
import { relatedColumnErrors } from "./view-related-column.js";
|
|
8
8
|
import { editableErrors } from "./view-editable.js";
|
|
9
9
|
import { conditionProblems } from "@protobase/layout";
|
|
10
|
-
import { actionInputErrors, addressErrors, addressPlaceholders, boardErrors,
|
|
10
|
+
import { actionInputErrors, addressErrors, addressPlaceholders, boardErrors, chartFields, datesErrors, displayFields, fieldRefsIn, hrefField, hrefPlaceholders, layoutItems, linkActionError, promptError, promptFields, updateSetErrors, viewOfList } from "@protobase/schema/internal";
|
|
11
11
|
import { isRecordCondition } from "@protobase/schema";
|
|
12
12
|
//#region src/check-views.ts
|
|
13
13
|
const linkFields = (run) => run?.kind !== "link" ? [] : "to" in run ? addressPlaceholders(run.to) : hrefPlaceholders(run.href);
|
|
@@ -147,7 +147,7 @@ const listOfErrors = (model, name, models) => {
|
|
|
147
147
|
* has a section, related section or sidebar whose `when` condition names what the app does not have, a related section or related list column, a cards display's or gallery's photos or a cards display's favorite button, a `listOf`, a "Save search" button or a
|
|
148
148
|
* `searchesOf` that do not fit the resources, cards
|
|
149
149
|
* displays of one list that name different photos, a chart per value that cannot group or add up its fields, a map that cannot show the
|
|
150
|
-
* record's position or a map display that cannot find the records in its view, a board whose columns are no filterable enum, a calendar whose dates are no filterable date or timestamp fields, a link to an address the app does not have, an AI action that cannot write its field, action inputs that do not fit, or a create page that is not one of `pages`.
|
|
150
|
+
* record's position or a map display that cannot find the records in its view, a board whose columns are no filterable enum, a calendar or timeline whose dates are no filterable date or timestamp fields, a link to an address the app does not have, an AI action that cannot write its field, action inputs that do not fit, or a create page that is not one of `pages`.
|
|
151
151
|
*/
|
|
152
152
|
const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
|
|
153
153
|
const models = Object.fromEntries(registry.entries.map((entry) => [entry.name, entry.model]));
|
|
@@ -165,7 +165,7 @@ const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
|
|
|
165
165
|
const searches = [...view.saveSearch ? saveSearchErrors(view.saveSearch, view.resource, models, views).map((error) => `saveSearch: ${error}`) : [], ...view.searchesOf ? searchesOfErrors(view.searchesOf, view.resource, models).map((error) => `searchesOf: ${error}`) : []];
|
|
166
166
|
const maps = [...layoutItems(view.layout).flatMap((item) => item.kind === "map" ? mapErrors(item, model).map((error) => `map "${item.title}": ${error}`) : []), ...(view.list?.displays ?? []).flatMap((display) => display.kind === "map" ? mapDisplayErrors(display, model).map((error) => `display "${display.name}": ${error}`) : [])];
|
|
167
167
|
const boards = (view.list?.displays ?? []).flatMap((display) => display.kind === "board" ? boardErrors(display, model).map((error) => `display "${display.name}": ${error}`) : []);
|
|
168
|
-
const calendars = (view.list?.displays ?? []).flatMap((display) => display.kind === "calendar" ?
|
|
168
|
+
const calendars = (view.list?.displays ?? []).flatMap((display) => display.kind === "calendar" || display.kind === "timeline" ? datesErrors(display, model).map((error) => `display "${display.name}": ${error}`) : []);
|
|
169
169
|
const chart = view.chart ? chartErrors(view.chart, model).map((error) => `chart: ${error}`) : [];
|
|
170
170
|
const history = model.history ? [] : layoutItems(view.layout).flatMap((item) => item.kind === "history" ? [`history "${item.title}" needs .history() on resource "${view.resource}"`] : []);
|
|
171
171
|
const comments = model.comments ? [] : layoutItems(view.layout).flatMap((item) => item.kind === "comments" ? [`comments "${item.title}" needs .comments() on resource "${view.resource}"`] : []);
|
package/dist/create-admin.js
CHANGED
|
@@ -53,6 +53,7 @@ import { batchRoute } from "./routes/batch.js";
|
|
|
53
53
|
import { collectionRoutes } from "./routes/collection.js";
|
|
54
54
|
import { docsRoutes } from "./routes/docs.js";
|
|
55
55
|
import { metaRoutes } from "./routes/meta.js";
|
|
56
|
+
import { webManifestRoute } from "./web-app/web-manifest-route.js";
|
|
56
57
|
import { recordRoutes } from "./routes/record.js";
|
|
57
58
|
import { createScanGuard } from "./scan-guard.js";
|
|
58
59
|
import { failedJobs, failedJobsView } from "./jobs/failed-jobs.js";
|
|
@@ -177,7 +178,8 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
|
|
|
177
178
|
...options.onUnhandledError && { report: options.onUnhandledError }
|
|
178
179
|
} }
|
|
179
180
|
};
|
|
180
|
-
const
|
|
181
|
+
const appName = auth?.appName ?? readAppName(globalThis.process?.env ?? {}) ?? "Protobase";
|
|
182
|
+
const meta = createMeta(deps, appName);
|
|
181
183
|
const onError = createErrorHandler(options.onUnhandledError);
|
|
182
184
|
const guarded = (routes, caller = authenticate) => {
|
|
183
185
|
const app = new Hono();
|
|
@@ -265,6 +267,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
|
|
|
265
267
|
}
|
|
266
268
|
app.route(basePath, api);
|
|
267
269
|
app.route(`${deps.systemPath}/meta`, metaApp);
|
|
270
|
+
app.route(systemPath || "/", webManifestRoute(appName));
|
|
268
271
|
app.route(deps.systemPath || "/", system);
|
|
269
272
|
const webhooks = createWebhooks({
|
|
270
273
|
deps,
|
package/dist/view-access.js
CHANGED
|
@@ -120,6 +120,16 @@ const listShape = (resource, model, models, prompted) => shapes.object({
|
|
|
120
120
|
end: shapes.field,
|
|
121
121
|
title: shapes.field
|
|
122
122
|
}, { requires: ["start"] }),
|
|
123
|
+
timeline: shapes.object({
|
|
124
|
+
kind: shapes.data,
|
|
125
|
+
name: shapes.data,
|
|
126
|
+
label: shapes.data,
|
|
127
|
+
icon: shapes.data,
|
|
128
|
+
start: shapes.field,
|
|
129
|
+
end: shapes.field,
|
|
130
|
+
group: shapes.field,
|
|
131
|
+
title: shapes.field
|
|
132
|
+
}, { requires: ["start"] }),
|
|
123
133
|
custom: shapes.object({
|
|
124
134
|
kind: shapes.data,
|
|
125
135
|
name: shapes.data,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { webManifest } from "./web-manifest.js";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
//#region src/web-app/web-manifest-route.ts
|
|
4
|
+
/** The path under the system path (`/api`) the admin app's page links its manifest at. */
|
|
5
|
+
const webManifestPath = "/manifest.webmanifest";
|
|
6
|
+
/** Answers the web app manifest to anyone: the browser fetches it without the user's token, before they sign in. */
|
|
7
|
+
const webManifestRoute = (appName) => {
|
|
8
|
+
const app = new Hono();
|
|
9
|
+
const body = JSON.stringify(webManifest(appName));
|
|
10
|
+
app.get(webManifestPath, () => new Response(body, { headers: {
|
|
11
|
+
"content-type": "application/manifest+json",
|
|
12
|
+
"cache-control": "no-cache"
|
|
13
|
+
} }));
|
|
14
|
+
return app;
|
|
15
|
+
};
|
|
16
|
+
//#endregion
|
|
17
|
+
export { webManifestPath, webManifestRoute };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/web-app/web-manifest.ts
|
|
2
|
+
/** Where the app's favicon is on its own origin, which `protobase build` and `protobase dev` always answer. */
|
|
3
|
+
const faviconPath = "/protobase.favicon.svg";
|
|
4
|
+
/**
|
|
5
|
+
* The web app manifest that makes the admin app installable: named for the app, opening at its home page in a window
|
|
6
|
+
* of its own, with the favicon as its icon. An SVG with `sizes: "any"` meets Chrome's 192 and 512 pixel icon sizes.
|
|
7
|
+
*/
|
|
8
|
+
const webManifest = (appName) => ({
|
|
9
|
+
name: appName,
|
|
10
|
+
short_name: appName,
|
|
11
|
+
id: "/",
|
|
12
|
+
start_url: "/",
|
|
13
|
+
scope: "/",
|
|
14
|
+
display: "standalone",
|
|
15
|
+
icons: [{
|
|
16
|
+
src: faviconPath,
|
|
17
|
+
sizes: "any",
|
|
18
|
+
type: "image/svg+xml"
|
|
19
|
+
}]
|
|
20
|
+
});
|
|
21
|
+
//#endregion
|
|
22
|
+
export { faviconPath, webManifest };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protobase/server",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.8",
|
|
4
4
|
"description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@better-auth/passkey": "^1.7.7",
|
|
33
33
|
"@better-auth/sso": "^1.7.7",
|
|
34
|
-
"@protobase/layout": "0.23.
|
|
35
|
-
"@protobase/query": "0.23.
|
|
36
|
-
"@protobase/schema": "0.23.
|
|
34
|
+
"@protobase/layout": "0.23.8",
|
|
35
|
+
"@protobase/query": "0.23.8",
|
|
36
|
+
"@protobase/schema": "0.23.8",
|
|
37
37
|
"@react-email/render": "^2.1.0",
|
|
38
38
|
"@scalar/hono-api-reference": "^0.12.10",
|
|
39
39
|
"@sentry/core": "^11.7.0",
|