@protobase/server 0.18.0 → 0.19.0
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-view-queries.d.ts +5 -0
- package/dist/check-view-queries.js +41 -0
- package/dist/check-views.js +16 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/view-access.js +19 -4
- package/package.json +4 -4
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ResourceModel, ViewModel } from "@protobase/schema";
|
|
2
|
+
//#region src/check-view-queries.d.ts
|
|
3
|
+
/** Throws one error listing what every view asks for that its resource does not allow; views of unknown resources are left to the other checks. */
|
|
4
|
+
export declare const checkViewQueries: (models: ResourceModel[], views: ViewModel[]) => void;
|
|
5
|
+
//#endregion
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/check-view-queries.ts
|
|
2
|
+
const widgetName = {
|
|
3
|
+
facets: "facets filter",
|
|
4
|
+
range: "range filter",
|
|
5
|
+
dateRange: "date range filter",
|
|
6
|
+
toggle: "toggle",
|
|
7
|
+
flags: "flags filter"
|
|
8
|
+
};
|
|
9
|
+
const filterableErrors = (model, names, what) => names.flatMap((name) => {
|
|
10
|
+
const field = Object.hasOwn(model.fields, name) ? model.fields[name] : void 0;
|
|
11
|
+
if (!field) return [`${what} names "${name}", which is not a field of ${model.name}`];
|
|
12
|
+
return field.filterable ? [] : [`${what} uses "${name}", which is not filterable, so the API refuses it: mark "${name}" .filterable()`];
|
|
13
|
+
});
|
|
14
|
+
const listSortErrors = (model, view) => (view.list?.sort ?? []).flatMap(([name]) => {
|
|
15
|
+
const field = Object.hasOwn(model.fields, name) ? model.fields[name] : void 0;
|
|
16
|
+
if (!field) return [`the list sorts by "${name}", which is not a field of ${model.name}`];
|
|
17
|
+
return field.sortable ? [] : [`the list sorts by "${name}", which is not sortable, so the API refuses it: mark "${name}" .sortable()`];
|
|
18
|
+
});
|
|
19
|
+
const searchErrors = (model, view) => (view.list?.search ?? []).filter((name) => !(model.search ?? []).includes(name)).map((name) => `the list searches "${name}", which ${model.name} does not search: add it to the resource's .search(...)`);
|
|
20
|
+
/**
|
|
21
|
+
* What a view asks the API for that its resource does not allow, which the API refuses only once a page asks: a filter
|
|
22
|
+
* widget or the chart on a field that is not `.filterable()`, a list sorted by one that is not `.sortable()`, and a list
|
|
23
|
+
* search on a field the resource does not search. The server's startup checks the rest of a view.
|
|
24
|
+
*/
|
|
25
|
+
const viewQueryErrors = (view, model) => [
|
|
26
|
+
...view.filters.flatMap((widget) => filterableErrors(model, widget.kind === "flags" ? widget.fields : [widget.field], `the ${widgetName[widget.kind]}`)),
|
|
27
|
+
...view.chart ? filterableErrors(model, [view.chart.field], "the chart") : [],
|
|
28
|
+
...listSortErrors(model, view),
|
|
29
|
+
...searchErrors(model, view)
|
|
30
|
+
];
|
|
31
|
+
/** Throws one error listing what every view asks for that its resource does not allow; views of unknown resources are left to the other checks. */
|
|
32
|
+
const checkViewQueries = (models, views) => {
|
|
33
|
+
const byName = new Map(models.map((model) => [model.name, model]));
|
|
34
|
+
const problems = views.flatMap((view) => {
|
|
35
|
+
const model = byName.get(view.resource);
|
|
36
|
+
return model ? viewQueryErrors(view, model).map((problem) => `View "${view.resource}": ${problem}`) : [];
|
|
37
|
+
});
|
|
38
|
+
if (problems.length > 0) throw new Error(`The views ask for what their resources do not allow:\n${problems.map((problem) => ` - ${problem}`).join("\n")}`);
|
|
39
|
+
};
|
|
40
|
+
//#endregion
|
|
41
|
+
export { checkViewQueries, viewQueryErrors };
|
package/dist/check-views.js
CHANGED
|
@@ -21,6 +21,7 @@ const sensitiveErrors = (view, model) => {
|
|
|
21
21
|
["the chart", view.chart ? [view.chart.field] : []],
|
|
22
22
|
["the sidebar", view.layout.flatMap((item) => item.kind === "sidebar" ? item.fields : [])],
|
|
23
23
|
["a map", view.layout.flatMap((item) => item.kind === "map" ? [item.latitude, item.longitude] : [])],
|
|
24
|
+
["a gallery", view.layout.flatMap((item) => item.kind === "gallery" && item.image !== void 0 ? [item.image] : [])],
|
|
24
25
|
["the recent records", view.nav?.recent ? [view.nav.recent.status] : []],
|
|
25
26
|
["an action", view.actions.flatMap((action) => action.run?.kind === "update" ? Object.keys(action.run.values) : linkFields(action.run))]
|
|
26
27
|
].flatMap(([place, names]) => [...new Set(names.filter(sensitive))].map((name) => `sensitive field "${name}" cannot be in ${place}`));
|
|
@@ -55,7 +56,11 @@ const linkErrors = (view, model, models, pages) => view.actions.flatMap(({ name,
|
|
|
55
56
|
});
|
|
56
57
|
const unknownFieldErrors = (view, model) => {
|
|
57
58
|
const unknown = (names, what) => names.filter((name) => !Object.hasOwn(model.fields, name)).map((name) => `${what} names field "${name}", which ${model.name} does not have`);
|
|
58
|
-
return [
|
|
59
|
+
return [
|
|
60
|
+
...(view.list?.displays ?? []).flatMap((display) => unknown(displayFields(display), `display "${display.name}"`)),
|
|
61
|
+
...view.layout.flatMap((item) => item.kind === "custom" ? unknown(fieldRefsIn(item.props), `custom section ${item.component}`) : []),
|
|
62
|
+
...view.layout.flatMap((item) => item.kind === "gallery" && item.image !== void 0 ? unknown([item.image], `gallery "${item.title}"`) : [])
|
|
63
|
+
];
|
|
59
64
|
};
|
|
60
65
|
const widgetErrors = (view, model, fieldTypes) => Object.entries(view.fields).flatMap(([name, hints]) => {
|
|
61
66
|
const of = hints.widget && fieldTypes[hints.widget.name];
|
|
@@ -71,6 +76,10 @@ const sharedPhotosErrors = (view) => {
|
|
|
71
76
|
const same = (a, b) => a.resource === b.resource && a.field === b.field && a.image === b.image && a.sort === b.sort;
|
|
72
77
|
return shown.filter(({ photos }) => !same(photos, shown[0].photos)).map(({ name }) => `display "${name}" photos: the list's records load with one set of photos, so name those of display "${shown[0].name}"`);
|
|
73
78
|
};
|
|
79
|
+
const galleryErrors = (item, resource, model, models) => {
|
|
80
|
+
const image = item.image === void 0 ? void 0 : model.fields[item.image];
|
|
81
|
+
return [...image && image.type !== "file" ? [`"${item.image}" is not a file field`] : [], ...item.photos ? cardPhotosErrors(item.photos, resource, models).map((error) => `photos: ${error}`) : []];
|
|
82
|
+
};
|
|
74
83
|
const listOfErrors = (model, name, models) => {
|
|
75
84
|
const target = models[model.fields[name]?.relation?.resource ?? ""];
|
|
76
85
|
if (!target) return [`"${name}" points at no resource of the app`];
|
|
@@ -80,7 +89,7 @@ const listOfErrors = (model, name, models) => {
|
|
|
80
89
|
* Fails at startup when a view uses a sensitive field where it would show empty, a display or custom section names a
|
|
81
90
|
* field the resource does not have, labels or colours values its enum does not have, shows a field with a field type of
|
|
82
91
|
* `fieldTypes` (each with the storage types it shows) that does not show it,
|
|
83
|
-
* has a related section, a cards display's photos or favorite button, a `listOf`, a "Save search" button or a
|
|
92
|
+
* has a related section, a cards display's or gallery's photos or a cards display's favorite button, a `listOf`, a "Save search" button or a
|
|
84
93
|
* `searchesOf` that do not fit the resources, cards
|
|
85
94
|
* displays of one list that name different photos, a map that cannot show the
|
|
86
95
|
* record's position or a map display that cannot find the records in its view, or a link to an address the app does not have.
|
|
@@ -92,7 +101,11 @@ const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
|
|
|
92
101
|
const model = models[view.resource];
|
|
93
102
|
if (!model) return [];
|
|
94
103
|
const related = view.layout.flatMap((item) => item.kind === "related" ? relatedErrors(item, view.resource, models).map((error) => `related "${item.title}": ${error}`) : []);
|
|
95
|
-
const photos = [
|
|
104
|
+
const photos = [
|
|
105
|
+
...(view.list?.displays ?? []).flatMap((display) => display.kind === "cards" && display.photos ? cardPhotosErrors(display.photos, view.resource, models).map((error) => `display "${display.name}" photos: ${error}`) : []),
|
|
106
|
+
...sharedPhotosErrors(view),
|
|
107
|
+
...view.layout.flatMap((item) => item.kind === "gallery" ? galleryErrors(item, view.resource, model, models).map((error) => `gallery "${item.title}": ${error}`) : [])
|
|
108
|
+
];
|
|
96
109
|
const favorites = (view.list?.displays ?? []).flatMap((display) => display.kind === "cards" && display.favorite ? [...cardFavoriteErrors(display.favorite, view.resource, models), ...favoriteOwnerErrors(display.favorite, models)].map((error) => `display "${display.name}" favorite: ${error}`) : []);
|
|
97
110
|
const listOf = view.listOf === void 0 ? [] : listOfErrors(model, view.listOf, models).map((error) => `listOf: ${error}`);
|
|
98
111
|
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}`) : []];
|
package/dist/index.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ import { MapOptions, mapStyleUrl, mapStyleVariable } from "./maps/map-settings.j
|
|
|
37
37
|
import { RuntimeOptions, runtimeUrl, runtimeVariable, seesRuntime } from "./runtime/runtime-settings.js";
|
|
38
38
|
import { AdminOptions } from "./admin-options.js";
|
|
39
39
|
import { CreateAdminInput, createAdmin } from "./create-admin.js";
|
|
40
|
+
import { checkViewQueries } from "./check-view-queries.js";
|
|
40
41
|
import { ProjectConfig, defineConfig, mergeConfig } from "./project-config.js";
|
|
41
42
|
import { consoleAuditQueue } from "./audit/console-queue.js";
|
|
42
43
|
import { JwtOptions, jwtAuthenticator } from "./auth/jwt.js";
|
|
@@ -82,4 +83,4 @@ import { FatalJobError } from "./jobs/run-job.js";
|
|
|
82
83
|
import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/runtime.js";
|
|
83
84
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
84
85
|
import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
|
|
85
|
-
export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSource, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapOptions, type MemberInput, MissingCredentials, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, betterAuthAuthenticator, changesMigration, checkAuthSchema, checkChanges, checkJobsSchema, checkSourceNames, checkWebhooksSchema, coalesce, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, hasUsers, imageSize, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
|
86
|
+
export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSource, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapOptions, type MemberInput, MissingCredentials, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, betterAuthAuthenticator, changesMigration, checkAuthSchema, checkChanges, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, hasUsers, imageSize, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ import { checkSourceNames, sourceOptions, sourcesFor, sourcesVariable } from "./
|
|
|
42
42
|
import { renderVariant, thumbHash } from "./files/images.js";
|
|
43
43
|
import { createAdmin } from "./create-admin.js";
|
|
44
44
|
import { configExports } from "./resource-source.js";
|
|
45
|
+
import { checkViewQueries } from "./check-view-queries.js";
|
|
45
46
|
import { defineConfig, mergeConfig } from "./project-config.js";
|
|
46
47
|
import { jwtAuthenticator } from "./auth/jwt.js";
|
|
47
48
|
import { withTrustedApps } from "./better-auth/app-tokens.js";
|
|
@@ -63,4 +64,4 @@ import { aspectRatio, fileSize, fileType, imageSize, processor } from "./files/p
|
|
|
63
64
|
import { defineEmail } from "./mail/define-email.js";
|
|
64
65
|
import { startJobs } from "./jobs/runtime.js";
|
|
65
66
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
66
|
-
export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, betterAuthAuthenticator, changesMigration, checkAuthSchema, checkChanges, checkJobsSchema, checkSourceNames, checkWebhooksSchema, coalesce, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, hasUsers, imageSize, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
|
67
|
+
export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, betterAuthAuthenticator, changesMigration, checkAuthSchema, checkChanges, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, hasUsers, imageSize, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
|
package/dist/view-access.js
CHANGED
|
@@ -14,6 +14,17 @@ const pruneRelated = (item, resource, models) => {
|
|
|
14
14
|
} : rest;
|
|
15
15
|
return relatedErrors(narrowed, resource, models).length === 0 ? narrowed : void 0;
|
|
16
16
|
};
|
|
17
|
+
const pruneGallery = (item, resource, model, models) => {
|
|
18
|
+
const image = item.image !== void 0 && Object.hasOwn(model.fields, item.image) ? item.image : void 0;
|
|
19
|
+
const photos = item.photos && cardPhotosErrors(item.photos, resource, models).length === 0 ? item.photos : void 0;
|
|
20
|
+
if (image === void 0 && photos === void 0) return void 0;
|
|
21
|
+
return {
|
|
22
|
+
kind: "gallery",
|
|
23
|
+
title: item.title,
|
|
24
|
+
...image !== void 0 && { image },
|
|
25
|
+
...photos && { photos }
|
|
26
|
+
};
|
|
27
|
+
};
|
|
17
28
|
const keepDefault = ({ default: opens, displays, ...list }) => {
|
|
18
29
|
const shown = displays && displays.length > 0 ? displays : void 0;
|
|
19
30
|
const kept = opens === tableDisplay || shown?.some((display) => display.name === opens);
|
|
@@ -97,11 +108,12 @@ const widgetShape = shapes.oneOf({
|
|
|
97
108
|
label: shapes.data
|
|
98
109
|
}, { requires: ["fields"] })
|
|
99
110
|
});
|
|
100
|
-
const layoutShape = (resource, models) => shapes.oneOf({
|
|
111
|
+
const layoutShape = (resource, model, models) => shapes.oneOf({
|
|
101
112
|
section: shapes.object({
|
|
102
113
|
kind: shapes.data,
|
|
103
114
|
title: shapes.data,
|
|
104
115
|
help: shapes.data,
|
|
116
|
+
helpWhen: shapes.data,
|
|
105
117
|
fields: shapes.list(shapes.field, { nonEmpty: true })
|
|
106
118
|
}, { requires: ["fields"] }),
|
|
107
119
|
sidebar: shapes.object({
|
|
@@ -123,7 +135,8 @@ const layoutShape = (resource, models) => shapes.oneOf({
|
|
|
123
135
|
longitude: shapes.field,
|
|
124
136
|
zoom: shapes.data,
|
|
125
137
|
sidebar: shapes.data
|
|
126
|
-
}, { requires: ["latitude", "longitude"] })
|
|
138
|
+
}, { requires: ["latitude", "longitude"] }),
|
|
139
|
+
gallery: shapes.map((item) => pruneGallery(item, resource, model, models))
|
|
127
140
|
});
|
|
128
141
|
const linkShape = (model, models) => shapes.map((run) => {
|
|
129
142
|
return ("to" in run ? addressErrors(run.to, {
|
|
@@ -166,12 +179,14 @@ const viewShape = (resource, model, models, prompted) => shapes.object({
|
|
|
166
179
|
fields: shapes.keys(),
|
|
167
180
|
list: listShape(resource, models, prompted),
|
|
168
181
|
filters: shapes.list(widgetShape),
|
|
169
|
-
layout: shapes.list(layoutShape(resource, models)),
|
|
182
|
+
layout: shapes.list(layoutShape(resource, model, models)),
|
|
170
183
|
chart: shapes.object({
|
|
171
184
|
field: shapes.field,
|
|
172
185
|
range: shapes.data,
|
|
173
186
|
granularity: shapes.data
|
|
174
187
|
}, { requires: ["field"] }),
|
|
188
|
+
recordMode: shapes.data,
|
|
189
|
+
helpWhen: shapes.data,
|
|
175
190
|
saveFeedback: shapes.data,
|
|
176
191
|
actions: shapes.list(actionShape(model, models)),
|
|
177
192
|
listOf: shapes.field,
|
|
@@ -181,7 +196,7 @@ const viewShape = (resource, model, models, prompted) => shapes.object({
|
|
|
181
196
|
});
|
|
182
197
|
/**
|
|
183
198
|
* The view with every reference to a field the caller cannot read removed: list columns, sort, search and displays,
|
|
184
|
-
* field hints, filter widgets, record sections, maps and custom components' props, the chart, title and search result, the
|
|
199
|
+
* field hints, filter widgets, record sections, maps, galleries and custom components' props, the chart, title and search result, the
|
|
185
200
|
* actions that set or read one, and the sidebar's `recent` group. Nothing in it may name a hidden field. Related sections
|
|
186
201
|
* and links are checked against `models`, the caller's view of every resource, and so are `searchesOf`, cards' favorite
|
|
187
202
|
* buttons and the "Save search" button; the buttons stay for a visitor when their resource is one of `prompted`, those
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protobase/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
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.
|
|
34
|
-
"@protobase/query": "0.
|
|
35
|
-
"@protobase/schema": "0.
|
|
33
|
+
"@protobase/layout": "0.19.0",
|
|
34
|
+
"@protobase/query": "0.19.0",
|
|
35
|
+
"@protobase/schema": "0.19.0",
|
|
36
36
|
"@react-email/render": "^2.1.0",
|
|
37
37
|
"@scalar/hono-api-reference": "^0.12.10",
|
|
38
38
|
"@sentry/core": "^11.7.0",
|