@protobase/schema 0.54.5 → 0.55.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.
@@ -0,0 +1,9 @@
1
+ //#region src/built-in-field-types.d.ts
2
+ /**
3
+ * The field types Protobase brings, which a view chooses with `.widget(name)` like a plugin's, by the storage types
4
+ * each shows: `members`, a JSON array of the user ids of an organization's members. A plugin's of the same name wins.
5
+ */
6
+ export declare const builtInFieldTypes: {
7
+ readonly members: readonly ["json"];
8
+ };
9
+ //#endregion
@@ -0,0 +1,8 @@
1
+ //#region src/built-in-field-types.ts
2
+ /**
3
+ * The field types Protobase brings, which a view chooses with `.widget(name)` like a plugin's, by the storage types
4
+ * each shows: `members`, a JSON array of the user ids of an organization's members. A plugin's of the same name wins.
5
+ */
6
+ const builtInFieldTypes = { members: ["json"] };
7
+ //#endregion
8
+ export { builtInFieldTypes };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Rollup, RollupCount, RollupFn, RollupSource, RollupValue } from "./computed/rollup.js";
2
2
  import { FileOptions, FileProcessor, FileProcessorInput, ImageFormat, ImageVariant, ImageVariantOptions, imageFormats } from "./files/file-options.js";
3
- import { ActionInputKind, ActionInputModel, ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CalendarView, CardFavoriteModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CommentsSectionModel, CompareOp, CreateModel, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, ExportModel, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, FormModel, GalleryModel, GroupChartModel, GroupItemModel, GroupModel, HelpWhen, HistorySectionModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListDragModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NamedListModel, NavModel, NavRecentModel, NowValue, OrderByItem, ParentAccess, ParentModel, PeriodChartModel, PositionAfterModel, RecordChartModel, RecordChartRange, RecordMode, RecordWhen, RelatedColumnModel, RelatedModel, RelatedPresentation, ResourceModel, SaveFeedback, SaveSearchModel, SearchMatch, SearchResultModel, SearchesOfModel, SectionModel, SectionPresentation, ShowWhen, SignInPromptModel, SignInViewModel, SortSpec, Span, StatusTone, TabItemModel, TabModel, TimelineView, UserMenuItemModel, UserMenuModel, ViewModel } from "./model.js";
3
+ import { ActionInputKind, ActionInputModel, ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CalendarView, CardFavoriteModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CommentsSectionModel, CompareOp, CreateModel, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, ExportModel, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, FormModel, GalleryModel, GroupChartModel, GroupItemModel, GroupModel, HelpWhen, HistorySectionModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListDragModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NamedListModel, NavModel, NavRecentModel, NowValue, OrderByItem, ParentAccess, ParentModel, PeriodChartModel, PositionAfterModel, RecordChartModel, RecordChartRange, RecordMode, RecordWhen, RelatedColumnModel, RelatedModel, RelatedPresentation, ResourceModel, SaveFeedback, SaveSearchModel, SearchMatch, SearchResultModel, SearchesOfModel, SectionModel, SectionPresentation, ShowWhen, SignInPromptModel, SignInViewModel, SortSpec, Span, StatusTone, TabItemModel, TabModel, TimelineView, TitleFromModel, UserMenuItemModel, UserMenuModel, ViewModel } from "./model.js";
4
4
  import { AccessAction, AccessContext, AccessFn, AccessResult, AccessUser, FieldAccess, FieldRule } from "./access/types.js";
5
5
  import { Encrypted, encrypted } from "./encrypted-value.js";
6
6
  import { AnyField, Constraint, Field, FieldMeta, FieldTypeDef } from "./field.js";
@@ -47,4 +47,4 @@ import { AccessSource, ResolveOptions, ResolvedAccess, RowFilterOperation, acces
47
47
  import { restrictModel } from "./access/restrict.js";
48
48
  import "./access/index.js";
49
49
  import { AssistantAction, AssistantActionRequest, AssistantCardPart, AssistantDiff, AssistantEvent, AssistantMessage, AssistantMessageRequest, AssistantPart, AssistantState, AssistantStep, AssistantStepState, AssistantTablePart, AssistantTextPart, AssistantTone, AssistantWidgetPart } from "./assistant/protocol.js";
50
- export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionInputKind, type ActionInputModel, type ActionModel, type ActionRun, type AnyField, type AppAddress, type ArgumentSpec, type ArgumentType, type ArgumentsSpec, type AssistantAction, type AssistantActionRequest, type AssistantCardPart, type AssistantDiff, type AssistantEvent, type AssistantMessage, type AssistantMessageRequest, type AssistantPart, type AssistantState, type AssistantStep, type AssistantStepState, type AssistantTablePart, type AssistantTextPart, type AssistantTone, type AssistantWidgetPart, type BadgeShape, type BottomBarItemModel, type BottomBarModel, type BottomBarNames, type BottomBarSource, type CalendarView, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartInput, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CommentsSectionModel, type CompareOp, type ComponentRef, type ComputedReveal, type ConnectAddress, type Constraint, type CreateModel, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type Encrypted, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type ExactCapability, type ExportModel, type Field, type FieldAccess, type FieldFormat, type FieldMeta, type FieldModel, type FieldPath, type FieldRefValue, type FieldRefs, type FieldRule, type FieldType, type FieldTypeDef, type FieldView, type FieldViewModel, type FieldViews, type FieldWidgetModel, type FieldsInput, type FileField, type FileFieldModel, type FileOptions, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type FormAddress, type FormInput, type FormModel, type GalleryModel, type Grant, type GroupChartInput, type GroupChartModel, type GroupItemModel, type GroupModel, type HeldCapability, type HelpWhen, type HistorySectionModel, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListColumn, type ListDisplayModel, type ListDragModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NamedListModel, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type ParentAccess, type ParentModel, type PeriodChartInput, type PeriodChartModel, type PositionAfterModel, type RecordChartModel, type RecordChartRange, type RecordKey, type RecordMode, type RecordOf, type RecordWhen, type Ref, type Refs, type RelatedColumnModel, type RelatedModel, type RelatedPresentation, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RevealCaller, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type Rollup, type RollupCount, type RollupFn, type RollupSource, type RollupValue, type RowFilterOperation, type Rule, type SaveFeedback, type SaveSearchModel, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SearchesOfModel, type SectionModel, type SectionPresentation, type ShowWhen, type SignInAddress, type SignInPromptModel, type SignInStep, type SignInViewModel, type SortSpec, type Span, type StatusTone, type TabItemModel, type TabModel, type TenantOptions, type TimelineView, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, argumentsSchema, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, connectParams, connectPath, connectRoute, createWhere, defineRoles, encrypted, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, fitsKeyType, formPath, formRoute, imageFormats, isRecordCondition, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, readConnectAddress, readFormAddress, readSignInAddress, resolveAccess, resource, restrictModel, rule, signInParams, signInPath, signInRoute, signInSteps, userMenu, view, where };
50
+ export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionInputKind, type ActionInputModel, type ActionModel, type ActionRun, type AnyField, type AppAddress, type ArgumentSpec, type ArgumentType, type ArgumentsSpec, type AssistantAction, type AssistantActionRequest, type AssistantCardPart, type AssistantDiff, type AssistantEvent, type AssistantMessage, type AssistantMessageRequest, type AssistantPart, type AssistantState, type AssistantStep, type AssistantStepState, type AssistantTablePart, type AssistantTextPart, type AssistantTone, type AssistantWidgetPart, type BadgeShape, type BottomBarItemModel, type BottomBarModel, type BottomBarNames, type BottomBarSource, type CalendarView, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartInput, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CommentsSectionModel, type CompareOp, type ComponentRef, type ComputedReveal, type ConnectAddress, type Constraint, type CreateModel, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type Encrypted, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type ExactCapability, type ExportModel, type Field, type FieldAccess, type FieldFormat, type FieldMeta, type FieldModel, type FieldPath, type FieldRefValue, type FieldRefs, type FieldRule, type FieldType, type FieldTypeDef, type FieldView, type FieldViewModel, type FieldViews, type FieldWidgetModel, type FieldsInput, type FileField, type FileFieldModel, type FileOptions, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type FormAddress, type FormInput, type FormModel, type GalleryModel, type Grant, type GroupChartInput, type GroupChartModel, type GroupItemModel, type GroupModel, type HeldCapability, type HelpWhen, type HistorySectionModel, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListColumn, type ListDisplayModel, type ListDragModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NamedListModel, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type ParentAccess, type ParentModel, type PeriodChartInput, type PeriodChartModel, type PositionAfterModel, type RecordChartModel, type RecordChartRange, type RecordKey, type RecordMode, type RecordOf, type RecordWhen, type Ref, type Refs, type RelatedColumnModel, type RelatedModel, type RelatedPresentation, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RevealCaller, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type Rollup, type RollupCount, type RollupFn, type RollupSource, type RollupValue, type RowFilterOperation, type Rule, type SaveFeedback, type SaveSearchModel, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SearchesOfModel, type SectionModel, type SectionPresentation, type ShowWhen, type SignInAddress, type SignInPromptModel, type SignInStep, type SignInViewModel, type SortSpec, type Span, type StatusTone, type TabItemModel, type TabModel, type TenantOptions, type TimelineView, type TitleFromModel, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, argumentsSchema, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, connectParams, connectPath, connectRoute, createWhere, defineRoles, encrypted, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, fitsKeyType, formPath, formRoute, imageFormats, isRecordCondition, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, readConnectAddress, readFormAddress, readSignInAddress, resolveAccess, resource, restrictModel, rule, signInParams, signInPath, signInRoute, signInSteps, userMenu, view, where };
@@ -35,4 +35,5 @@ import { pushRecord, serviceWorkerFile } from "./push-record.js";
35
35
  import { deviceIdParam, devicesPath } from "./devices-path.js";
36
36
  import { historyIdParam, historyIdPattern, historyPath } from "./history-path.js";
37
37
  import { listColumnNames } from "./list-columns.js";
38
- export { type AddressCheck, type FormulaNode, type Locale, type MobileReleaseAnswer, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type SearchTerm, actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, boardErrors, bottomBarFor, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, datesErrors, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, renderPrompt, searchTerms, serviceWorkerFile, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
38
+ import { builtInFieldTypes } from "./built-in-field-types.js";
39
+ export { type AddressCheck, type FormulaNode, type Locale, type MobileReleaseAnswer, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type SearchTerm, actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, boardErrors, bottomBarFor, builtInFieldTypes, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, datesErrors, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, renderPrompt, searchTerms, serviceWorkerFile, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
package/dist/internal.js CHANGED
@@ -35,4 +35,5 @@ import { pushRecord, serviceWorkerFile } from "./push-record.js";
35
35
  import { deviceIdParam, devicesPath } from "./devices-path.js";
36
36
  import { historyIdParam, historyIdPattern, historyPath } from "./history-path.js";
37
37
  import { listColumnNames } from "./list-columns.js";
38
- export { actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, boardErrors, bottomBarFor, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, datesErrors, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, renderPrompt, searchTerms, serviceWorkerFile, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
38
+ import { builtInFieldTypes } from "./built-in-field-types.js";
39
+ export { actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, boardErrors, bottomBarFor, builtInFieldTypes, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, datesErrors, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, renderPrompt, searchTerms, serviceWorkerFile, shapes, shownInputs, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
package/dist/model.d.ts CHANGED
@@ -327,8 +327,9 @@ export type FieldViewModel = {
327
327
  /** `arrow` draws the field's badges as arrows pointing right, as on a rating scale such as the EU energy label. */
328
328
  badgeShape?: BadgeShape;
329
329
  /**
330
- * The field type a plugin registers (`definePlugin({ fields })`) that shows and edits this field, with its props;
331
- * without that plugin, or for a storage type it does not show, the field shows as it would without it.
330
+ * The field type a plugin registers (`definePlugin({ fields })`), or a built-in one such as `members`, that shows and
331
+ * edits this field, with its props; without it, or for a storage type it does not show, the field shows as it would
332
+ * without it.
332
333
  */
333
334
  widget?: FieldWidgetModel;
334
335
  };
@@ -611,7 +612,7 @@ export type ParentAccess = 'read' | 'update';
611
612
  /**
612
613
  * A record that a resource's records belong to through a relation field, such as an operation's VM: creating, changing,
613
614
  * deleting or undeleting a record needs `access` on the record `field` points at, checked with the caller's own access
614
- * rules on that resource. See
615
+ * rules on that resource; with `read`, every read of its records keeps to those whose parent the caller reads. See
615
616
  * [Records that belong to another](website/src/content/docs/reference/access.mdx#records-that-belong-to-another).
616
617
  */
617
618
  export type ParentModel = {
@@ -1220,6 +1221,19 @@ export type SearchResultModel = {
1220
1221
  /** The field on the line under it. */
1221
1222
  subtitle?: string;
1222
1223
  };
1224
+ /**
1225
+ * A record's title derived in the browser, for the person reading it: the project UI's `titles[rule]` gets the record's
1226
+ * `fields` and the reader, such as the names of a conversation's other members. Presentation only: it is no field,
1227
+ * filter or sort key. `unreadable` marks one that reads a field the caller cannot read, which then titles by the key.
1228
+ */
1229
+ export type TitleFromModel = {
1230
+ /** The name of the function under the project UI's `titles`. */
1231
+ rule: string;
1232
+ /** The fields the rule reads, which every request that titles a record asks for. */
1233
+ fields: string[];
1234
+ /** Set in `/meta` for a caller who cannot read one of the fields, which it then leaves out. */
1235
+ unreadable?: true;
1236
+ };
1223
1237
  /**
1224
1238
  * How the admin shows a resource: its names, list, filters, record page and actions, built by `view(...)` and sent to
1225
1239
  * each user in `/meta` without what they cannot see. See [Views](website/src/content/docs/reference/ui-config.mdx).
@@ -1231,6 +1245,8 @@ export type ViewModel = {
1231
1245
  roles?: string[];
1232
1246
  /** Field used as the record's display title in breadcrumbs, relation links and search results. */
1233
1247
  title?: string;
1248
+ /** A title the browser derives per reader in place of `title`, by a rule of the project's UI (see `TitleFromModel`). */
1249
+ titleFrom?: TitleFromModel;
1234
1250
  /** A record in the global search: a title of one or more fields joined by spaces, over a subtitle field by default. */
1235
1251
  searchResult?: SearchResultModel;
1236
1252
  /** Where the resource sits in the sidebar. */
@@ -114,8 +114,9 @@ export declare class ResourceBuilder<F extends FieldsInput = {}, K = never> {
114
114
  /**
115
115
  * A relation whose record each record belongs to, and the access on it writing them needs: creating a record, changing
116
116
  * it (the parent it leaves and the one it moves to), deleting and undeleting it all need `access` on the parent,
117
- * checked with the caller's own access rules on its resource and locked until the write commits. A null relation
118
- * checks nothing; each call adds a check. See
117
+ * checked with the caller's own access rules on its resource and locked until the write commits. With `read`, every
118
+ * read of its records (lists, counts, aggregates, gets and labels) also keeps to those whose parent the caller reads
119
+ * there. A null relation checks nothing; each call adds a check. See
119
120
  * [Records that belong to another](website/src/content/docs/reference/access.mdx#records-that-belong-to-another).
120
121
  *
121
122
  * @example
package/dist/resource.js CHANGED
@@ -121,8 +121,9 @@ var ResourceBuilder = class ResourceBuilder {
121
121
  /**
122
122
  * A relation whose record each record belongs to, and the access on it writing them needs: creating a record, changing
123
123
  * it (the parent it leaves and the one it moves to), deleting and undeleting it all need `access` on the parent,
124
- * checked with the caller's own access rules on its resource and locked until the write commits. A null relation
125
- * checks nothing; each call adds a check. See
124
+ * checked with the caller's own access rules on its resource and locked until the write commits. With `read`, every
125
+ * read of its records (lists, counts, aggregates, gets and labels) also keeps to those whose parent the caller reads
126
+ * there. A null relation checks nothing; each call adds a check. See
126
127
  * [Records that belong to another](website/src/content/docs/reference/access.mdx#records-that-belong-to-another).
127
128
  *
128
129
  * @example
@@ -67,7 +67,9 @@ export declare class FieldView<N extends string = string, V = unknown> {
67
67
  icon(icon: string): FieldView<N, V>;
68
68
  /**
69
69
  * Shows and edits the field with the field type a plugin registers under `name` (`definePlugin({ fields })`), given
70
- * `props`, such as `r.score.widget('rating', { max: 5 })`. Without that plugin, or when the field type does not show
70
+ * `props`, such as `r.score.widget('rating', { max: 5 })`, or with the built-in `members`, which picks an
71
+ * organization's members into a JSON array of user ids (see
72
+ * [Members](website/src/content/docs/reference/plugins.md#members)). Without that field type, or when it does not show
71
73
  * this field's storage type, the field shows as it would without it.
72
74
  */
73
75
  widget(name: string, props?: Record<string, JsonValue>): FieldView<N, V>;
@@ -103,7 +103,9 @@ var FieldView = class FieldView {
103
103
  }
104
104
  /**
105
105
  * Shows and edits the field with the field type a plugin registers under `name` (`definePlugin({ fields })`), given
106
- * `props`, such as `r.score.widget('rating', { max: 5 })`. Without that plugin, or when the field type does not show
106
+ * `props`, such as `r.score.widget('rating', { max: 5 })`, or with the built-in `members`, which picks an
107
+ * organization's members into a JSON array of user ids (see
108
+ * [Members](website/src/content/docs/reference/plugins.md#members)). Without that field type, or when it does not show
107
109
  * this field's storage type, the field shows as it would without it.
108
110
  */
109
111
  widget(name, props) {
package/dist/view.d.ts CHANGED
@@ -57,6 +57,12 @@ export declare class ViewBuilder<R extends {
57
57
  forRoles(roles: string[]): ViewBuilder<R>;
58
58
  /** The field shown as this record's title. Throws when the field does not exist. */
59
59
  title(pick: (r: FieldRefs<FieldsOf<R>>) => Ref): ViewBuilder<R>;
60
+ /**
61
+ * A title derived per reader in the browser, in place of `title`: `rule` names a function of the project's UI
62
+ * `titles`, which gets the record with the `fields` picked and the signed-in reader, such as the names of the members
63
+ * other than the reader. The record's key shows while it returns nothing. Throws when a field does not exist.
64
+ */
65
+ titleFrom(rule: string, pick: (r: FieldRefs<FieldsOf<R>>) => Ref[]): ViewBuilder<R>;
60
66
  /**
61
67
  * How a record shows in the global search: a bold `title` of one or more fields joined by spaces (default: `title`)
62
68
  * and a `subtitle` field under it, replaced by the search field the text matched when that is neither.
@@ -205,7 +211,7 @@ export declare class ViewBuilder<R extends {
205
211
  };
206
212
  limit?: number;
207
213
  }): ViewBuilder<R>;
208
- /** With the resource's model, also verifies the title, search result and list display fields, related column names, a gallery's image, `listOf`, `searchesOf`, the sidebar's `recent` group and `tenant`, and the forms' fields. */
214
+ /** With the resource's model, also verifies the title and `titleFrom`, search result and list display fields, related column names, a gallery's image, `listOf`, `searchesOf`, the sidebar's `recent` group and `tenant`, and the forms' fields. */
209
215
  toModel(resource?: ResourceModel): ViewModel;
210
216
  private refs;
211
217
  private next;
package/dist/view.js CHANGED
@@ -58,6 +58,20 @@ var ViewBuilder = class ViewBuilder {
58
58
  return this.next({ title: pick(this.refs()).name });
59
59
  }
60
60
  /**
61
+ * A title derived per reader in the browser, in place of `title`: `rule` names a function of the project's UI
62
+ * `titles`, which gets the record with the `fields` picked and the signed-in reader, such as the names of the members
63
+ * other than the reader. The record's key shows while it returns nothing. Throws when a field does not exist.
64
+ */
65
+ titleFrom(rule, pick) {
66
+ const fields = pick(this.refs()).map((ref) => ref.name);
67
+ if (rule === "") throw new Error(`View "${this.state.resource}": titleFrom needs the name of a rule`);
68
+ if (fields.length === 0) throw new Error(`View "${this.state.resource}": titleFrom "${rule}" reads no fields`);
69
+ return this.next({ titleFrom: {
70
+ rule,
71
+ fields
72
+ } });
73
+ }
74
+ /**
61
75
  * How a record shows in the global search: a bold `title` of one or more fields joined by spaces (default: `title`)
62
76
  * and a `subtitle` field under it, replaced by the search field the text matched when that is neither.
63
77
  */
@@ -287,10 +301,12 @@ var ViewBuilder = class ViewBuilder {
287
301
  };
288
302
  return this.next({ searchesOf: searches });
289
303
  }
290
- /** With the resource's model, also verifies the title, search result and list display fields, related column names, a gallery's image, `listOf`, `searchesOf`, the sidebar's `recent` group and `tenant`, and the forms' fields. */
304
+ /** With the resource's model, also verifies the title and `titleFrom`, search result and list display fields, related column names, a gallery's image, `listOf`, `searchesOf`, the sidebar's `recent` group and `tenant`, and the forms' fields. */
291
305
  toModel(resource) {
292
- const { title, nav, searchResult, list, listOf } = this.state;
306
+ const { title, titleFrom, nav, searchResult, list, listOf } = this.state;
293
307
  if (resource && title !== void 0 && !Object.hasOwn(resource.fields, title)) throw new Error(`View "${this.state.resource}": title field "${title}" does not exist on the resource`);
308
+ const unknownTitleField = resource ? titleFrom?.fields.find((name) => !Object.hasOwn(resource.fields, name)) : void 0;
309
+ if (unknownTitleField !== void 0) throw new Error(`View "${this.state.resource}": titleFrom field "${unknownTitleField}" does not exist on the resource`);
294
310
  const missing = resource ? [...searchResult?.title ?? [], ...searchResult?.subtitle ? [searchResult.subtitle] : []].filter((name) => !Object.hasOwn(resource.fields, name)) : [];
295
311
  if (missing.length > 0) throw new Error(`View "${this.state.resource}": search result field "${missing[0]}" does not exist on the resource`);
296
312
  for (const display of resource ? list?.displays ?? [] : []) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/schema",
3
- "version": "0.54.5",
3
+ "version": "0.55.0",
4
4
  "description": "Resource, field, view and access definitions for Protobase configs.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {