@protobase/server 0.21.10 → 0.21.12
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 +12 -3
- package/dist/view-access.js +59 -41
- package/package.json +4 -4
package/dist/check-views.js
CHANGED
|
@@ -6,7 +6,9 @@ import { chartErrors } from "./view-chart.js";
|
|
|
6
6
|
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
|
-
import {
|
|
9
|
+
import { conditionProblems } from "@protobase/layout";
|
|
10
|
+
import { actionInputErrors, addressErrors, addressPlaceholders, boardErrors, calendarErrors, chartFields, displayFields, fieldRefsIn, hrefField, hrefPlaceholders, layoutItems, linkActionError, promptError, promptFields } from "@protobase/schema/internal";
|
|
11
|
+
import { isRecordCondition } from "@protobase/schema";
|
|
10
12
|
//#region src/check-views.ts
|
|
11
13
|
const linkFields = (run) => run?.kind !== "link" ? [] : "to" in run ? addressPlaceholders(run.to) : hrefPlaceholders(run.href);
|
|
12
14
|
const actionFields = (run) => {
|
|
@@ -123,6 +125,12 @@ const galleryErrors = (item, resource, model, models) => {
|
|
|
123
125
|
const image = item.image === void 0 ? void 0 : model.fields[item.image];
|
|
124
126
|
return [...image && image.type !== "file" ? [`"${item.image}" is not a file field`] : [], ...item.photos ? cardPhotosErrors(item.photos, resource, models).map((error) => `photos: ${error}`) : []];
|
|
125
127
|
};
|
|
128
|
+
const conditionErrors = (view, models) => view.layout.flatMap((item) => {
|
|
129
|
+
if (item.kind !== "section" && item.kind !== "sidebar" && item.kind !== "related") return [];
|
|
130
|
+
if (!isRecordCondition(item.when)) return [];
|
|
131
|
+
const place = item.kind === "sidebar" ? "sidebar" : `${item.kind} "${item.title}"`;
|
|
132
|
+
return conditionProblems(item.when, view.resource, models).map((error) => `${place}: ${error}`);
|
|
133
|
+
});
|
|
126
134
|
const listOfErrors = (model, name, models) => {
|
|
127
135
|
const target = models[model.fields[name]?.relation?.resource ?? ""];
|
|
128
136
|
if (!target) return [`"${name}" points at no resource of the app`];
|
|
@@ -133,7 +141,7 @@ const listOfErrors = (model, name, models) => {
|
|
|
133
141
|
* field the resource does not have, labels or colours values its enum does not have, shows a field with a field type of
|
|
134
142
|
* `fieldTypes` (each with the storage types it shows) that does not show it,
|
|
135
143
|
* edits a list column in its cell that is not a field with an editor of one line the API may write,
|
|
136
|
-
* has 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
|
|
144
|
+
* 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
|
|
137
145
|
* `searchesOf` that do not fit the resources, cards
|
|
138
146
|
* 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
|
|
139
147
|
* 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`.
|
|
@@ -144,7 +152,7 @@ const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
|
|
|
144
152
|
const problems = views.flatMap((view) => {
|
|
145
153
|
const model = models[view.resource];
|
|
146
154
|
if (!model) return [];
|
|
147
|
-
const related = [...view.layout.flatMap((item) => item.kind === "related" ? relatedErrors(item, view.resource, models).map((error) => `related "${item.title}": ${error}`) : []), ...relatedColumnsErrors(view, model, models)];
|
|
155
|
+
const related = [...layoutItems(view.layout).flatMap((item) => item.kind === "related" ? relatedErrors(item, view.resource, models).map((error) => `related "${item.title}": ${error}`) : []), ...relatedColumnsErrors(view, model, models)];
|
|
148
156
|
const photos = [
|
|
149
157
|
...(view.list?.displays ?? []).flatMap((display) => display.kind === "cards" && display.photos ? cardPhotosErrors(display.photos, view.resource, models).map((error) => `display "${display.name}" photos: ${error}`) : []),
|
|
150
158
|
...sharedPhotosErrors(view),
|
|
@@ -168,6 +176,7 @@ const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
|
|
|
168
176
|
...listEditErrors(view, model),
|
|
169
177
|
...widgetErrors(view, model, fieldTypes),
|
|
170
178
|
...related,
|
|
179
|
+
...conditionErrors(view, models),
|
|
171
180
|
...photos,
|
|
172
181
|
...favorites,
|
|
173
182
|
...listOf,
|
package/dist/view-access.js
CHANGED
|
@@ -3,10 +3,12 @@ import { cardPhotosErrors } from "./view-card-photos.js";
|
|
|
3
3
|
import { cardFavoriteErrors } from "./view-card-favorite.js";
|
|
4
4
|
import { searchesOfFor } from "./view-saved-search.js";
|
|
5
5
|
import { relatedColumnErrors } from "./view-related-column.js";
|
|
6
|
-
import { resolveFieldPath } from "@protobase/layout";
|
|
6
|
+
import { conditionReadable, resolveFieldPath } from "@protobase/layout";
|
|
7
7
|
import { addressErrors, chartFields, hrefPlaceholders, navRecentErrors, promptFields, pruneByShape, shapes, tableDisplay } from "@protobase/schema/internal";
|
|
8
|
+
import { isRecordCondition } from "@protobase/schema";
|
|
8
9
|
//#region src/view-access.ts
|
|
9
10
|
const pruneRelated = (item, resource, models) => {
|
|
11
|
+
if (isRecordCondition(item.when) && !conditionReadable(item.when, resource, models)) return void 0;
|
|
10
12
|
const { columns, open, ...rest } = item;
|
|
11
13
|
const visible = models[item.resource] ? columns?.filter((column) => resolveFieldPath(models, item.resource, column).ok) : void 0;
|
|
12
14
|
const narrowed = visible && visible.length > 0 ? {
|
|
@@ -22,6 +24,7 @@ const pruneRelated = (item, resource, models) => {
|
|
|
22
24
|
} : narrowed;
|
|
23
25
|
return relatedErrors(opened, resource, models).length === 0 ? opened : void 0;
|
|
24
26
|
};
|
|
27
|
+
const recordWhenShape = (resource, models) => shapes.map((when) => isRecordCondition(when) && !conditionReadable(when, resource, models) ? void 0 : when);
|
|
25
28
|
const pruneGallery = (item, resource, model, models) => {
|
|
26
29
|
const image = item.image !== void 0 && Object.hasOwn(model.fields, item.image) ? item.image : void 0;
|
|
27
30
|
const photos = item.photos && cardPhotosErrors(item.photos, resource, models).length === 0 ? item.photos : void 0;
|
|
@@ -155,52 +158,67 @@ const widgetShape = shapes.oneOf({
|
|
|
155
158
|
label: shapes.data
|
|
156
159
|
}, { requires: ["fields"] })
|
|
157
160
|
});
|
|
158
|
-
const layoutShape = (resource, model, models) =>
|
|
159
|
-
|
|
161
|
+
const layoutShape = (resource, model, models) => {
|
|
162
|
+
const when = recordWhenShape(resource, models);
|
|
163
|
+
const section = shapes.object({
|
|
160
164
|
kind: shapes.data,
|
|
161
165
|
title: shapes.data,
|
|
162
166
|
help: shapes.data,
|
|
163
167
|
helpWhen: shapes.data,
|
|
164
168
|
presentation: shapes.data,
|
|
165
|
-
when
|
|
169
|
+
when,
|
|
166
170
|
fields: shapes.list(shapes.field, { nonEmpty: true })
|
|
167
|
-
}, { requires: ["fields"] })
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
})
|
|
171
|
+
}, { requires: ["fields", "when"] });
|
|
172
|
+
const related = shapes.map((item) => pruneRelated(item, resource, models));
|
|
173
|
+
return shapes.oneOf({
|
|
174
|
+
section,
|
|
175
|
+
sidebar: shapes.object({
|
|
176
|
+
kind: shapes.data,
|
|
177
|
+
fields: shapes.list(shapes.field, { nonEmpty: true }),
|
|
178
|
+
when
|
|
179
|
+
}, { requires: ["fields", "when"] }),
|
|
180
|
+
related,
|
|
181
|
+
group: shapes.object({
|
|
182
|
+
kind: shapes.data,
|
|
183
|
+
title: shapes.data,
|
|
184
|
+
collapsed: shapes.data,
|
|
185
|
+
when,
|
|
186
|
+
items: shapes.list(shapes.oneOf({
|
|
187
|
+
section,
|
|
188
|
+
related
|
|
189
|
+
}), { nonEmpty: true })
|
|
190
|
+
}, { requires: ["items", "when"] }),
|
|
191
|
+
custom: shapes.object({
|
|
192
|
+
kind: shapes.data,
|
|
193
|
+
component: shapes.data,
|
|
194
|
+
title: shapes.data,
|
|
195
|
+
sidebar: shapes.data,
|
|
196
|
+
when: shapes.data,
|
|
197
|
+
props: shapes.refs
|
|
198
|
+
}, { requires: ["props"] }),
|
|
199
|
+
map: shapes.object({
|
|
200
|
+
kind: shapes.data,
|
|
201
|
+
title: shapes.data,
|
|
202
|
+
latitude: shapes.field,
|
|
203
|
+
longitude: shapes.field,
|
|
204
|
+
zoom: shapes.data,
|
|
205
|
+
sidebar: shapes.data,
|
|
206
|
+
when: shapes.data
|
|
207
|
+
}, { requires: ["latitude", "longitude"] }),
|
|
208
|
+
gallery: shapes.map((item) => pruneGallery(item, resource, model, models)),
|
|
209
|
+
history: shapes.object({
|
|
210
|
+
kind: shapes.data,
|
|
211
|
+
title: shapes.data,
|
|
212
|
+
limit: shapes.data,
|
|
213
|
+
when: shapes.data
|
|
214
|
+
}),
|
|
215
|
+
comments: shapes.object({
|
|
216
|
+
kind: shapes.data,
|
|
217
|
+
title: shapes.data,
|
|
218
|
+
when: shapes.data
|
|
219
|
+
})
|
|
220
|
+
});
|
|
221
|
+
};
|
|
204
222
|
const linkShape = (model, models) => shapes.map((run) => {
|
|
205
223
|
return ("to" in run ? addressErrors(run.to, {
|
|
206
224
|
models,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protobase/server",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.12",
|
|
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.21.
|
|
35
|
-
"@protobase/query": "0.21.
|
|
36
|
-
"@protobase/schema": "0.21.
|
|
34
|
+
"@protobase/layout": "0.21.12",
|
|
35
|
+
"@protobase/query": "0.21.12",
|
|
36
|
+
"@protobase/schema": "0.21.12",
|
|
37
37
|
"@react-email/render": "^2.1.0",
|
|
38
38
|
"@scalar/hono-api-reference": "^0.12.10",
|
|
39
39
|
"@sentry/core": "^11.7.0",
|