@protobase/server 0.19.13 → 0.19.15

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.
@@ -4,7 +4,7 @@ import { cardFavoriteErrors, favoriteOwnerErrors } from "./view-card-favorite.js
4
4
  import { saveSearchErrors, searchesOfErrors } from "./view-saved-search.js";
5
5
  import { mapDisplayErrors, mapErrors } from "./view-map.js";
6
6
  import { relatedColumnErrors } from "./view-related-column.js";
7
- import { addressErrors, addressPlaceholders, displayFields, fieldRefsIn, hrefField, hrefPlaceholders, linkActionError } from "@protobase/schema/internal";
7
+ import { actionInputErrors, addressErrors, addressPlaceholders, displayFields, fieldRefsIn, hrefField, hrefPlaceholders, linkActionError } from "@protobase/schema/internal";
8
8
  //#region src/check-views.ts
9
9
  const linkFields = (run) => run?.kind !== "link" ? [] : "to" in run ? addressPlaceholders(run.to) : hrefPlaceholders(run.href);
10
10
  const sensitiveErrors = (view, model) => {
@@ -57,6 +57,14 @@ const linkErrors = (view, model, models, pages) => view.actions.flatMap(({ name,
57
57
  source: model
58
58
  }).map((error) => `action "${name}": ${error}`) : [];
59
59
  });
60
+ const inputErrors = (view, models) => view.actions.flatMap(({ name, run, inputs }) => {
61
+ if (!inputs) return [];
62
+ return [
63
+ ...run ? [`inputs need a handler, and a${run.kind === "update" ? "n" : ""} ${run.kind} action has none`] : [],
64
+ ...actionInputErrors(inputs),
65
+ ...inputs.flatMap((input) => input.resource !== void 0 && !models[input.resource] ? [`input "${input.name}" picks from resource "${input.resource}", which the app does not have`] : [])
66
+ ].map((error) => `action "${name}": ${error}`);
67
+ });
60
68
  const createErrors = (view, pages) => view.create && !pages.has(view.create.page) ? [`create: unknown page "${view.create.page}"`] : [];
61
69
  const unknownFieldErrors = (view, model) => {
62
70
  const unknown = (names, what) => names.filter((name) => !Object.hasOwn(model.fields, name)).map((name) => `${what} names field "${name}", which ${model.name} does not have`);
@@ -101,7 +109,7 @@ const listOfErrors = (model, name, models) => {
101
109
  * 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
102
110
  * `searchesOf` that do not fit the resources, cards
103
111
  * displays of one list that name different photos, a map that cannot show the
104
- * record's position or a map display that cannot find the records in its view, a link to an address the app does not have, or a create page that is not one of `pages`.
112
+ * record's position or a map display that cannot find the records in its view, a link to an address the app does not have, action inputs that do not fit, or a create page that is not one of `pages`.
105
113
  */
106
114
  const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
107
115
  const models = Object.fromEntries(registry.entries.map((entry) => [entry.name, entry.model]));
@@ -133,6 +141,7 @@ const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
133
141
  ...searches,
134
142
  ...maps,
135
143
  ...linkErrors(view, model, models, pageNames),
144
+ ...inputErrors(view, models),
136
145
  ...createErrors(view, pageNames)
137
146
  ].map((problem) => `View "${view.resource}": ${problem}`);
138
147
  });
@@ -23,7 +23,8 @@ const pruneGallery = (item, resource, model, models) => {
23
23
  kind: "gallery",
24
24
  title: item.title,
25
25
  ...image !== void 0 && { image },
26
- ...photos && { photos }
26
+ ...photos && { photos },
27
+ ...item.when !== void 0 && { when: item.when }
27
28
  };
28
29
  };
29
30
  const tidyList = (model) => ({ default: opens, displays, columns, relatedColumns, ...list }) => {
@@ -121,11 +122,13 @@ const layoutShape = (resource, model, models) => shapes.oneOf({
121
122
  help: shapes.data,
122
123
  helpWhen: shapes.data,
123
124
  presentation: shapes.data,
125
+ when: shapes.data,
124
126
  fields: shapes.list(shapes.field, { nonEmpty: true })
125
127
  }, { requires: ["fields"] }),
126
128
  sidebar: shapes.object({
127
129
  kind: shapes.data,
128
- fields: shapes.list(shapes.field, { nonEmpty: true })
130
+ fields: shapes.list(shapes.field, { nonEmpty: true }),
131
+ when: shapes.data
129
132
  }, { requires: ["fields"] }),
130
133
  related: shapes.map((item) => pruneRelated(item, resource, models)),
131
134
  custom: shapes.object({
@@ -133,6 +136,7 @@ const layoutShape = (resource, model, models) => shapes.oneOf({
133
136
  component: shapes.data,
134
137
  title: shapes.data,
135
138
  sidebar: shapes.data,
139
+ when: shapes.data,
136
140
  props: shapes.refs
137
141
  }, { requires: ["props"] }),
138
142
  map: shapes.object({
@@ -141,7 +145,8 @@ const layoutShape = (resource, model, models) => shapes.oneOf({
141
145
  latitude: shapes.field,
142
146
  longitude: shapes.field,
143
147
  zoom: shapes.data,
144
- sidebar: shapes.data
148
+ sidebar: shapes.data,
149
+ when: shapes.data
145
150
  }, { requires: ["latitude", "longitude"] }),
146
151
  gallery: shapes.map((item) => pruneGallery(item, resource, model, models))
147
152
  });
@@ -151,6 +156,7 @@ const linkShape = (model, models) => shapes.map((run) => {
151
156
  source: model
152
157
  }).length === 0 : hrefPlaceholders(run.href).every((name) => Object.hasOwn(model.fields, name))) ? run : void 0;
153
158
  });
159
+ const inputsShape = (models) => shapes.map((inputs) => inputs.every((input) => input.resource === void 0 || Object.hasOwn(models, input.resource)) ? inputs : void 0);
154
160
  const actionShape = (model, models) => shapes.object({
155
161
  name: shapes.data,
156
162
  label: shapes.data,
@@ -164,8 +170,9 @@ const actionShape = (model, models) => shapes.object({
164
170
  }, { requires: ["values"] }),
165
171
  delete: shapes.data,
166
172
  link: linkShape(model, models)
167
- })
168
- }, { requires: ["run"] });
173
+ }),
174
+ inputs: inputsShape(models)
175
+ }, { requires: ["run", "inputs"] });
169
176
  const viewShape = (resource, model, models, prompted) => shapes.object({
170
177
  resource: shapes.data,
171
178
  roles: shapes.data,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.19.13",
3
+ "version": "0.19.15",
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": {
@@ -30,9 +30,9 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@better-auth/passkey": "^1.7.7",
33
- "@protobase/layout": "0.19.13",
34
- "@protobase/query": "0.19.13",
35
- "@protobase/schema": "0.19.13",
33
+ "@protobase/layout": "0.19.15",
34
+ "@protobase/query": "0.19.15",
35
+ "@protobase/schema": "0.19.15",
36
36
  "@react-email/render": "^2.1.0",
37
37
  "@scalar/hono-api-reference": "^0.12.10",
38
38
  "@sentry/core": "^11.7.0",