@protobase/schema 0.13.4 → 0.14.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.
Files changed (57) hide show
  1. package/dist/access/capability.d.ts +3 -0
  2. package/dist/access/index.d.ts +3 -3
  3. package/dist/access/resolve.d.ts +13 -0
  4. package/dist/access/role-entry.d.ts +5 -0
  5. package/dist/access/roles.d.ts +14 -0
  6. package/dist/access/roles.js +11 -0
  7. package/dist/access/rule.d.ts +10 -0
  8. package/dist/access/rule.js +10 -0
  9. package/dist/access/types.d.ts +11 -0
  10. package/dist/assistant/protocol.d.ts +67 -2
  11. package/dist/bottom-bar-errors.d.ts +3 -0
  12. package/dist/bottom-bar.d.ts +3 -1
  13. package/dist/bottom-bar.js +2 -1
  14. package/dist/events/event-helpers.d.ts +41 -8
  15. package/dist/events/event-helpers.js +1 -3
  16. package/dist/field-ref.d.ts +1 -0
  17. package/dist/field.d.ts +54 -1
  18. package/dist/field.js +16 -0
  19. package/dist/fields.d.ts +31 -0
  20. package/dist/fields.js +31 -0
  21. package/dist/file-field.d.ts +6 -1
  22. package/dist/file-field.js +6 -1
  23. package/dist/files/file-options.d.ts +17 -0
  24. package/dist/filter/check.d.ts +5 -0
  25. package/dist/filter/evaluate.d.ts +1 -0
  26. package/dist/filter/order-by.d.ts +14 -0
  27. package/dist/filter/order-by.js +2 -0
  28. package/dist/filter/parse.d.ts +16 -2
  29. package/dist/filter/parse.js +8 -2
  30. package/dist/filter/where.d.ts +61 -0
  31. package/dist/filter/where.js +34 -0
  32. package/dist/index.d.ts +16 -24
  33. package/dist/index.js +6 -18
  34. package/dist/internal.d.ts +17 -0
  35. package/dist/internal.js +17 -0
  36. package/dist/keys.d.ts +1 -0
  37. package/dist/layout.d.ts +15 -0
  38. package/dist/layout.js +15 -0
  39. package/dist/model.d.ts +344 -6
  40. package/dist/refs.d.ts +6 -0
  41. package/dist/relation-field.d.ts +5 -0
  42. package/dist/relation-field.js +5 -0
  43. package/dist/resource-types.d.ts +18 -0
  44. package/dist/resource.d.ts +94 -6
  45. package/dist/resource.js +75 -2
  46. package/dist/user-menu.d.ts +5 -1
  47. package/dist/user-menu.js +4 -1
  48. package/dist/view-actions.d.ts +1 -0
  49. package/dist/view-displays.d.ts +3 -0
  50. package/dist/view-field.d.ts +14 -1
  51. package/dist/view-field.js +7 -0
  52. package/dist/view-widgets.d.ts +7 -0
  53. package/dist/view-widgets.js +7 -0
  54. package/dist/view.d.ts +52 -4
  55. package/dist/view.js +39 -2
  56. package/dist/webhooks/webhook-resources.js +1 -1
  57. package/package.json +3 -2
@@ -2,57 +2,118 @@ import { FilterExpr, FilterValue } from "../model.js";
2
2
  import { Field } from "../field.js";
3
3
  import { RecordOf } from "../resource-types.js";
4
4
  //#region src/filter/where.d.ts
5
+ /** @inline */
5
6
  type Scalar = string | number | boolean;
7
+ /** @inline */
6
8
  type Source = {
9
+ /** The resource's fields, as `resource(...)` declares them. */
7
10
  readonly $fields: unknown;
8
11
  };
12
+ /** @inline */
9
13
  type Fields<R extends Source> = keyof RecordOf<R['$fields']> & string;
14
+ /** @inline */
10
15
  type Value<R extends Source, K extends Fields<R>> = Extract<NonNullable<RecordOf<R['$fields']>[K]>, Scalar> | FilterValue;
16
+ /** @inline */
11
17
  type Anything = {
18
+ /** Any fields: names and values are not checked. */
12
19
  readonly $fields: Record<string, Field<any>>;
13
20
  };
21
+ /**
22
+ * Builds filters in code, for the client and the UI, as `where` does, with field names and values typed against the
23
+ * resource `R`: `createWhere<typeof orders>().eq('status', 'paid')`. A filter it builds prints as filter text with
24
+ * `printFilter`.
25
+ */
14
26
  export declare const createWhere: <R extends Source = Anything>() => {
27
+ /** The field equals the value: `status = "paid"`. */
15
28
  eq: <K extends Fields<R>>(name: K, value: Value<R, K>) => FilterExpr;
29
+ /** The field differs from the value: `status != "paid"`. */
16
30
  ne: <K extends Fields<R>>(name: K, value: Value<R, K>) => FilterExpr;
31
+ /** The field is below the value: `total < 100`. */
17
32
  lt: <K extends Fields<R>>(name: K, value: Value<R, K>) => FilterExpr;
33
+ /** The field is at most the value: `total <= 100`. */
18
34
  lte: <K extends Fields<R>>(name: K, value: Value<R, K>) => FilterExpr;
35
+ /** The field is above the value: `total > 100`. */
19
36
  gt: <K extends Fields<R>>(name: K, value: Value<R, K>) => FilterExpr;
37
+ /** The field is at least the value: `total >= 100`. */
20
38
  gte: <K extends Fields<R>>(name: K, value: Value<R, K>) => FilterExpr;
39
+ /** The field lies from `low` to `high`, both included. */
21
40
  between: <K extends Fields<R>>(name: K, low: Value<R, K>, high: Value<R, K>) => FilterExpr;
41
+ /** A JSON field holds the value, as a key or an element: `tags:"urgent"`. */
22
42
  has: <K extends Fields<R>>(name: K, value: Scalar) => FilterExpr;
43
+ /** The field has a value, a JSON field one other than `null`: `field:*`. */
23
44
  present: <K extends Fields<R>>(name: K) => FilterExpr;
45
+ /** The field equals one of the values: `in(status, "paid", "sent")`. */
24
46
  in: <K extends Fields<R>>(name: K, values: Extract<NonNullable<RecordOf<R["$fields"]>[K]>, Scalar>[]) => FilterExpr;
47
+ /** The field has no value: `isNull(field)`. */
25
48
  isNull: <K extends Fields<R>>(name: K) => FilterExpr;
49
+ /** Every word of the text appears, ignoring case, in one of the resource's search fields: `search("text")`. */
26
50
  search: (text: string) => FilterExpr;
51
+ /** The text field is close to the text by trigram similarity, typos included: `similar(field, "text")`. */
27
52
  similar: <K extends Fields<R>>(name: K, text: string) => FilterExpr;
53
+ /** The text field matches the regular expression, ignoring case: `regex(field, "pattern")`. */
28
54
  regex: <K extends Fields<R>>(name: K, pattern: string) => FilterExpr;
55
+ /** Every filter holds; one filter is returned as it is, none throws. */
29
56
  and: (...args: FilterExpr[]) => FilterExpr;
57
+ /** At least one filter holds; one filter is returned as it is, none throws. */
30
58
  or: (...args: FilterExpr[]) => FilterExpr;
59
+ /** The filter does not hold. */
31
60
  not: (arg: FilterExpr) => FilterExpr;
61
+ /** The current time, as a value to compare with: `now()`. */
32
62
  now: () => FilterValue;
63
+ /** A time the duration before now, such as `ago('7d')` for `now() - 7d`; units are `s`, `m`, `h`, `d` and `w`. */
33
64
  ago: (duration: string) => FilterValue;
65
+ /** A time the duration after now, such as `fromNow('1h')` for `now() + 1h`. */
34
66
  fromNow: (duration: string) => FilterValue;
35
67
  };
68
+ /**
69
+ * Builds a filter in code instead of writing filter text, for any resource; `createWhere` checks names and values
70
+ * against one. The [Filters](website/src/content/docs/reference/api.md#filters) of the API take what it builds.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * where.and(where.eq('status', 'paid'), where.gte('created_at', where.ago('30d')))
75
+ * ```
76
+ */
36
77
  export declare const where: {
78
+ /** The field equals the value: `status = "paid"`. */
37
79
  eq: <K extends string>(name: K, value: any) => FilterExpr;
80
+ /** The field differs from the value: `status != "paid"`. */
38
81
  ne: <K extends string>(name: K, value: any) => FilterExpr;
82
+ /** The field is below the value: `total < 100`. */
39
83
  lt: <K extends string>(name: K, value: any) => FilterExpr;
84
+ /** The field is at most the value: `total <= 100`. */
40
85
  lte: <K extends string>(name: K, value: any) => FilterExpr;
86
+ /** The field is above the value: `total > 100`. */
41
87
  gt: <K extends string>(name: K, value: any) => FilterExpr;
88
+ /** The field is at least the value: `total >= 100`. */
42
89
  gte: <K extends string>(name: K, value: any) => FilterExpr;
90
+ /** The field lies from `low` to `high`, both included. */
43
91
  between: <K extends string>(name: K, low: any, high: any) => FilterExpr;
92
+ /** A JSON field holds the value, as a key or an element: `tags:"urgent"`. */
44
93
  has: <K extends string>(name: K, value: Scalar) => FilterExpr;
94
+ /** The field has a value, a JSON field one other than `null`: `field:*`. */
45
95
  present: <K extends string>(name: K) => FilterExpr;
96
+ /** The field equals one of the values: `in(status, "paid", "sent")`. */
46
97
  in: <K extends string>(name: K, values: any[]) => FilterExpr;
98
+ /** The field has no value: `isNull(field)`. */
47
99
  isNull: <K extends string>(name: K) => FilterExpr;
100
+ /** Every word of the text appears, ignoring case, in one of the resource's search fields: `search("text")`. */
48
101
  search: (text: string) => FilterExpr;
102
+ /** The text field is close to the text by trigram similarity, typos included: `similar(field, "text")`. */
49
103
  similar: <K extends string>(name: K, text: string) => FilterExpr;
104
+ /** The text field matches the regular expression, ignoring case: `regex(field, "pattern")`. */
50
105
  regex: <K extends string>(name: K, pattern: string) => FilterExpr;
106
+ /** Every filter holds; one filter is returned as it is, none throws. */
51
107
  and: (...args: FilterExpr[]) => FilterExpr;
108
+ /** At least one filter holds; one filter is returned as it is, none throws. */
52
109
  or: (...args: FilterExpr[]) => FilterExpr;
110
+ /** The filter does not hold. */
53
111
  not: (arg: FilterExpr) => FilterExpr;
112
+ /** The current time, as a value to compare with: `now()`. */
54
113
  now: () => FilterValue;
114
+ /** A time the duration before now, such as `ago('7d')` for `now() - 7d`; units are `s`, `m`, `h`, `d` and `w`. */
55
115
  ago: (duration: string) => FilterValue;
116
+ /** A time the duration after now, such as `fromNow('1h')` for `now() + 1h`. */
56
117
  fromNow: (duration: string) => FilterValue;
57
118
  };
58
119
  //#endregion
@@ -38,6 +38,11 @@ const group = (kind, args) => {
38
38
  span
39
39
  };
40
40
  };
41
+ /**
42
+ * Builds filters in code, for the client and the UI, as `where` does, with field names and values typed against the
43
+ * resource `R`: `createWhere<typeof orders>().eq('status', 'paid')`. A filter it builds prints as filter text with
44
+ * `printFilter`.
45
+ */
41
46
  const createWhere = () => {
42
47
  const compare = (op) => (name, value) => ({
43
48
  kind: "compare",
@@ -55,67 +60,96 @@ const createWhere = () => {
55
60
  span
56
61
  });
57
62
  return {
63
+ /** The field equals the value: `status = "paid"`. */
58
64
  eq: compare("="),
65
+ /** The field differs from the value: `status != "paid"`. */
59
66
  ne: compare("!="),
67
+ /** The field is below the value: `total < 100`. */
60
68
  lt: compare("<"),
69
+ /** The field is at most the value: `total <= 100`. */
61
70
  lte: compare("<="),
71
+ /** The field is above the value: `total > 100`. */
62
72
  gt: compare(">"),
73
+ /** The field is at least the value: `total >= 100`. */
63
74
  gte: compare(">="),
75
+ /** The field lies from `low` to `high`, both included. */
64
76
  between: (name, low, high) => group("and", [compare(">=")(name, low), compare("<=")(name, high)]),
77
+ /** A JSON field holds the value, as a key or an element: `tags:"urgent"`. */
65
78
  has: (name, value) => ({
66
79
  kind: "has",
67
80
  field: field(name),
68
81
  value: literal(value),
69
82
  span
70
83
  }),
84
+ /** The field has a value, a JSON field one other than `null`: `field:*`. */
71
85
  present: (name) => ({
72
86
  kind: "present",
73
87
  field: field(name),
74
88
  span
75
89
  }),
90
+ /** The field equals one of the values: `in(status, "paid", "sent")`. */
76
91
  in: (name, values) => ({
77
92
  kind: "in",
78
93
  field: field(name),
79
94
  values: values.map(literal),
80
95
  span
81
96
  }),
97
+ /** The field has no value: `isNull(field)`. */
82
98
  isNull: (name) => ({
83
99
  kind: "isNull",
84
100
  field: field(name),
85
101
  span
86
102
  }),
103
+ /** Every word of the text appears, ignoring case, in one of the resource's search fields: `search("text")`. */
87
104
  search: (text) => ({
88
105
  kind: "search",
89
106
  text,
90
107
  span
91
108
  }),
109
+ /** The text field is close to the text by trigram similarity, typos included: `similar(field, "text")`. */
92
110
  similar: (name, text) => ({
93
111
  kind: "similar",
94
112
  field: field(name),
95
113
  text,
96
114
  span
97
115
  }),
116
+ /** The text field matches the regular expression, ignoring case: `regex(field, "pattern")`. */
98
117
  regex: (name, pattern) => ({
99
118
  kind: "regex",
100
119
  field: field(name),
101
120
  pattern,
102
121
  span
103
122
  }),
123
+ /** Every filter holds; one filter is returned as it is, none throws. */
104
124
  and: (...args) => group("and", args),
125
+ /** At least one filter holds; one filter is returned as it is, none throws. */
105
126
  or: (...args) => group("or", args),
127
+ /** The filter does not hold. */
106
128
  not: (arg) => ({
107
129
  kind: "not",
108
130
  arg,
109
131
  span
110
132
  }),
133
+ /** The current time, as a value to compare with: `now()`. */
111
134
  now: () => ({
112
135
  kind: "now",
113
136
  span
114
137
  }),
138
+ /** A time the duration before now, such as `ago('7d')` for `now() - 7d`; units are `s`, `m`, `h`, `d` and `w`. */
115
139
  ago: offset("-"),
140
+ /** A time the duration after now, such as `fromNow('1h')` for `now() + 1h`. */
116
141
  fromNow: offset("+")
117
142
  };
118
143
  };
144
+ /**
145
+ * Builds a filter in code instead of writing filter text, for any resource; `createWhere` checks names and values
146
+ * against one. The [Filters](website/src/content/docs/reference/api.md#filters) of the API take what it builds.
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * where.and(where.eq('status', 'paid'), where.gte('created_at', where.ago('30d')))
151
+ * ```
152
+ */
119
153
  const where = createWhere();
120
154
  //#endregion
121
155
  export { createWhere, where };
package/dist/index.d.ts CHANGED
@@ -1,31 +1,25 @@
1
- import { FileProcessor, FileProcessorInput, ImageFormat, ImageVariant, ImageVariantOptions, checkedAccept, checkedProvider, imageFormats, parseSize } from "./files/file-options.js";
1
+ import { FileOptions, FileProcessor, FileProcessorInput, ImageFormat, ImageVariant, ImageVariantOptions, imageFormats } from "./files/file-options.js";
2
2
  import { ActionModel, ActionRun, AppAddress, BadgeShape, BottomBarItemModel, BottomBarModel, CardPhotosModel, ChartGranularity, ChartModel, ChartRange, CheckedFilter, CompareOp, CustomSectionModel, DatePreset, DurationLiteral, DurationUnit, EventModel, EventOperation, FieldFormat, FieldModel, FieldPath, FieldType, FieldViewModel, FieldWidgetModel, FileFieldModel, FilterError, FilterErrorCode, FilterExpr, FilterLayout, FilterOf, FilterValue, FilterWidgetModel, JsonValue, KeyValue, LayoutItemModel, ListDisplayModel, ListModel, ListQuery, Literal, MapSectionModel, MapView, NavModel, NavRecentModel, NowValue, OrderByItem, RelatedModel, ResourceModel, SaveFeedback, SearchMatch, SearchResultModel, SortSpec, Span, StatusTone, UserMenuItemModel, UserMenuModel, ViewModel } from "./model.js";
3
3
  import { AccessAction, AccessContext, AccessFn, AccessResult, AccessUser, FieldAccess, FieldRule } from "./access/types.js";
4
- import { Field } from "./field.js";
4
+ import { AnyField, Constraint, Field, FieldMeta, FieldTypeDef } from "./field.js";
5
+ import { RelationField } from "./relation-field.js";
5
6
  import { FileField } from "./file-field.js";
6
7
  import { f } from "./fields.js";
7
- import { EventActor, EventContext, EventHelpers, EventMatch, EventSpec } from "./events/event-helpers.js";
8
- import { InferRecord, RecordKey } from "./resource-types.js";
9
- import { resource } from "./resource.js";
10
- import { checkEventFilter } from "./events/event-models.js";
11
- import { ComponentRef, ViewProps, displayFields, tableDisplay } from "./view-displays.js";
12
- import { view } from "./view.js";
13
- import { webhookResources } from "./webhooks/webhook-resources.js";
14
- import { FieldRefValue, fieldRef, fieldRefsIn, isFieldRef, markFieldRefs, unmarkFieldRefs } from "./field-ref.js";
15
- import { PropShapes, RefShape, pruneByShape, shapes } from "./ref-shape.js";
8
+ import { FieldRefs, FieldsInput, Ref, Refs } from "./refs.js";
9
+ import { CreatedOptions, DeletedOptions, EventActor, EventContext, EventHelpers, EventMatch, EventSpec, UndeletedOptions, UpdatedOptions } from "./events/event-helpers.js";
10
+ import { Access, InferRecord, Issue, KeyOf, KeyRefs, RecordKey, RecordOf } from "./resource-types.js";
11
+ import { ResourceBuilder, SearchRef, SearchRefs, Validator, resource } from "./resource.js";
12
+ import { ComponentRef, ViewProps } from "./view-displays.js";
13
+ import { FieldView } from "./view-field.js";
14
+ import { FieldViews, ViewBuilder, view } from "./view.js";
15
+ import { FieldRefValue, fieldRef } from "./field-ref.js";
16
16
  import { enumLabel } from "./enum-label.js";
17
- import { SearchTerm, matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
18
- import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
19
17
  import { UserMenuSource, userMenu } from "./user-menu.js";
20
- import { BottomBarSource, bottomBar, bottomBarFor, maxBottomBarItems } from "./bottom-bar.js";
18
+ import { BottomBarSource, bottomBar, maxBottomBarItems } from "./bottom-bar.js";
21
19
  import { BottomBarNames, bottomBarErrors } from "./bottom-bar-errors.js";
22
20
  import { layout } from "./layout.js";
23
- import { KeyType, decodeKey, encodeKey, keyTypes } from "./keys.js";
21
+ import { KeyType, keyTypes } from "./keys.js";
24
22
  import { addressWords, appPath, readAppPath } from "./app-address.js";
25
- import { PluginHost, PluginRequirement, inRange, pluginProblem } from "./plugin-version.js";
26
- import { redactSecrets } from "./redact-secrets.js";
27
- import { addressPlaceholders, appHrefError, fillAddress, hrefPlaceholders, leavesApp } from "./address-template.js";
28
- import { AddressCheck, addressErrors } from "./address-errors.js";
29
23
  import { FilterLimits, FilterParse, parseFilter } from "./filter/parse.js";
30
24
  import { CheckResult, checkFilter } from "./filter/check.js";
31
25
  import { EvaluateOptions, evaluateFilter } from "./filter/evaluate.js";
@@ -33,8 +27,8 @@ import { printFilter } from "./filter/print.js";
33
27
  import { OrderByCheck, OrderByParse, checkOrderBy, parseOrderBy, printOrderBy } from "./filter/order-by.js";
34
28
  import { createWhere, where } from "./filter/where.js";
35
29
  import "./filter/index.js";
36
- import { Capability, CapabilityAction, CapabilityScope } from "./access/capability.js";
37
- import { CapabilityLimit, RoleEntry, anonymousRole } from "./access/role-entry.js";
30
+ import { Capability, CapabilityAction, CapabilityScope, Grant } from "./access/capability.js";
31
+ import { CapabilityLimit, HeldCapability, RoleEntry, anonymousRole } from "./access/role-entry.js";
38
32
  import { Rule, rule } from "./access/rule.js";
39
33
  import { RoleLimit, Roles, RolesOptions, defineRoles } from "./access/roles.js";
40
34
  import { pickView } from "./access/pick-view.js";
@@ -42,6 +36,4 @@ import { AccessSource, ResolveOptions, ResolvedAccess, RowFilterOperation, acces
42
36
  import { restrictModel } from "./access/restrict.js";
43
37
  import "./access/index.js";
44
38
  import { AssistantAction, AssistantActionRequest, AssistantCardPart, AssistantDiff, AssistantEvent, AssistantMessage, AssistantMessageRequest, AssistantPart, AssistantState, AssistantStep, AssistantStepState, AssistantTablePart, AssistantTextPart, AssistantTone, AssistantWidgetPart } from "./assistant/protocol.js";
45
- import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
46
- import { readEventStream } from "./assistant/event-stream.js";
47
- export { type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionModel, type ActionRun, type AddressCheck, type AppAddress, 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 Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardPhotosModel, type ChartGranularity, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CompareOp, type ComponentRef, type CustomSectionModel, type DatePreset, type DurationLiteral, type DurationUnit, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type Field, type FieldAccess, type FieldFormat, type FieldModel, type FieldPath, type FieldRefValue, type FieldRule, type FieldType, type FieldViewModel, type FieldWidgetModel, type FileField, type FileFieldModel, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type JsonValue, type KeyType, type KeyValue, type LayoutItemModel, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type PluginHost, type PluginRequirement, type PropShapes, type RecordKey, type RefShape, type RelatedModel, type ResolveOptions, type ResolvedAccess, type ResourceModel, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type RowFilterOperation, type Rule, type SaveFeedback, type SearchMatch, type SearchResultModel, type SearchTerm, type SortSpec, type Span, type StatusTone, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type ViewModel, type ViewProps, accessWarnings, addressErrors, addressPlaceholders, addressWords, anonymousRole, appHrefError, appPath, applyAssistantEvent, bottomBar, bottomBarErrors, bottomBarFor, checkEventFilter, checkFilter, checkOrderBy, checkRecord, checkedAccept, checkedProvider, createWhere, decodeKey, defaultRecentLimit, defineRoles, displayFields, emptyAssistantState, encodeKey, enumLabel, evaluateFilter, f, fieldRef, fieldRefsIn, fieldsUsedBy, fillAddress, hrefPlaceholders, imageFormats, inRange, isFieldRef, keyTypes, layout as l, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, maxBottomBarItems, navRecentErrors, parseFilter, parseOrderBy, parseSize, pickView, pluginProblem, printFilter, printOrderBy, pruneByShape, readAppPath, readEventStream, redactSecrets, resolveAccess, resource, restrictModel, rule, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, userMenu, view, webhookResources, where };
39
+ export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionModel, type ActionRun, type AnyField, type AppAddress, 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 Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardPhotosModel, type ChartGranularity, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CompareOp, type ComponentRef, type Constraint, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, 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 Grant, type HeldCapability, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type RecordKey, type RecordOf, type Ref, type Refs, type RelatedModel, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type RowFilterOperation, type Rule, type SaveFeedback, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SortSpec, type Span, type StatusTone, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, resolveAccess, resource, restrictModel, rule, userMenu, view, where };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { checkedAccept, checkedProvider, imageFormats, parseSize } from "./files/file-options.js";
1
+ import { imageFormats } from "./files/file-options.js";
2
2
  import { f } from "./fields.js";
3
3
  import { parseFilter } from "./filter/parse.js";
4
4
  import { checkFilter } from "./filter/check.js";
@@ -8,30 +8,18 @@ import { checkOrderBy, parseOrderBy, printOrderBy } from "./filter/order-by.js";
8
8
  import { createWhere, where } from "./filter/where.js";
9
9
  import { anonymousRole } from "./access/role-entry.js";
10
10
  import { accessWarnings, checkRecord, fieldsUsedBy, resolveAccess } from "./access/resolve.js";
11
- import { checkEventFilter } from "./events/event-models.js";
12
11
  import { resource } from "./resource.js";
13
- import { fieldRef, fieldRefsIn, isFieldRef, markFieldRefs, unmarkFieldRefs } from "./field-ref.js";
14
- import { displayFields, tableDisplay } from "./view-displays.js";
15
- import { layout } from "./layout.js";
16
- import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
17
- import { addressPlaceholders, appHrefError, fillAddress, hrefPlaceholders, leavesApp } from "./address-template.js";
12
+ import { fieldRef } from "./field-ref.js";
18
13
  import { view } from "./view.js";
19
- import { webhookResources } from "./webhooks/webhook-resources.js";
20
- import { pruneByShape, shapes } from "./ref-shape.js";
21
14
  import { enumLabel } from "./enum-label.js";
22
- import { matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
23
15
  import { userMenu } from "./user-menu.js";
24
- import { bottomBar, bottomBarFor, maxBottomBarItems } from "./bottom-bar.js";
16
+ import { bottomBar, maxBottomBarItems } from "./bottom-bar.js";
25
17
  import { bottomBarErrors } from "./bottom-bar-errors.js";
26
- import { decodeKey, encodeKey, keyTypes } from "./keys.js";
18
+ import { layout } from "./layout.js";
19
+ import { keyTypes } from "./keys.js";
27
20
  import { addressWords, appPath, readAppPath } from "./app-address.js";
28
- import { inRange, pluginProblem } from "./plugin-version.js";
29
- import { redactSecrets } from "./redact-secrets.js";
30
- import { addressErrors } from "./address-errors.js";
31
21
  import { rule } from "./access/rule.js";
32
22
  import { defineRoles } from "./access/roles.js";
33
23
  import { pickView } from "./access/pick-view.js";
34
24
  import { restrictModel } from "./access/restrict.js";
35
- import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
36
- import { readEventStream } from "./assistant/event-stream.js";
37
- export { accessWarnings, addressErrors, addressPlaceholders, addressWords, anonymousRole, appHrefError, appPath, applyAssistantEvent, bottomBar, bottomBarErrors, bottomBarFor, checkEventFilter, checkFilter, checkOrderBy, checkRecord, checkedAccept, checkedProvider, createWhere, decodeKey, defaultRecentLimit, defineRoles, displayFields, emptyAssistantState, encodeKey, enumLabel, evaluateFilter, f, fieldRef, fieldRefsIn, fieldsUsedBy, fillAddress, hrefPlaceholders, imageFormats, inRange, isFieldRef, keyTypes, layout as l, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, maxBottomBarItems, navRecentErrors, parseFilter, parseOrderBy, parseSize, pickView, pluginProblem, printFilter, printOrderBy, pruneByShape, readAppPath, readEventStream, redactSecrets, resolveAccess, resource, restrictModel, rule, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, userMenu, view, webhookResources, where };
25
+ export { accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, resolveAccess, resource, restrictModel, rule, userMenu, view, where };
@@ -0,0 +1,17 @@
1
+ import { checkedAccept, checkedProvider, parseSize } from "./files/file-options.js";
2
+ import { displayFields, tableDisplay } from "./view-displays.js";
3
+ import { fieldRefsIn, isFieldRef, markFieldRefs, unmarkFieldRefs } from "./field-ref.js";
4
+ import { bottomBarFor } from "./bottom-bar.js";
5
+ import { decodeKey, encodeKey } from "./keys.js";
6
+ import { checkEventFilter } from "./events/event-models.js";
7
+ import { webhookResources } from "./webhooks/webhook-resources.js";
8
+ import { PropShapes, RefShape, pruneByShape, shapes } from "./ref-shape.js";
9
+ import { SearchTerm, matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
10
+ import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
11
+ import { PluginHost, PluginRequirement, inRange, pluginProblem } from "./plugin-version.js";
12
+ import { redactSecrets } from "./redact-secrets.js";
13
+ import { addressPlaceholders, appHrefError, fillAddress, hrefPlaceholders, leavesApp } from "./address-template.js";
14
+ import { AddressCheck, addressErrors } from "./address-errors.js";
15
+ import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
16
+ import { readEventStream } from "./assistant/event-stream.js";
17
+ export { type AddressCheck, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type SearchTerm, addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, bottomBarFor, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefPlaceholders, inRange, isFieldRef, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, pruneByShape, readEventStream, redactSecrets, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, webhookResources };
@@ -0,0 +1,17 @@
1
+ import { checkedAccept, checkedProvider, parseSize } from "./files/file-options.js";
2
+ import { checkEventFilter } from "./events/event-models.js";
3
+ import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
4
+ import { addressPlaceholders, appHrefError, fillAddress, hrefPlaceholders, leavesApp } from "./address-template.js";
5
+ import { fieldRefsIn, isFieldRef, markFieldRefs, unmarkFieldRefs } from "./field-ref.js";
6
+ import { displayFields, tableDisplay } from "./view-displays.js";
7
+ import { bottomBarFor } from "./bottom-bar.js";
8
+ import { decodeKey, encodeKey } from "./keys.js";
9
+ import { webhookResources } from "./webhooks/webhook-resources.js";
10
+ import { pruneByShape, shapes } from "./ref-shape.js";
11
+ import { matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
12
+ import { inRange, pluginProblem } from "./plugin-version.js";
13
+ import { redactSecrets } from "./redact-secrets.js";
14
+ import { addressErrors } from "./address-errors.js";
15
+ import { applyAssistantEvent, emptyAssistantState } from "./assistant/apply-event.js";
16
+ import { readEventStream } from "./assistant/event-stream.js";
17
+ export { addressErrors, addressPlaceholders, appHrefError, applyAssistantEvent, bottomBarFor, checkEventFilter, checkedAccept, checkedProvider, decodeKey, defaultRecentLimit, displayFields, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, hrefPlaceholders, inRange, isFieldRef, leavesApp, markFieldRefs, matchedSearchField, matchesSearch, navRecentErrors, parseSize, pluginProblem, pruneByShape, readEventStream, redactSecrets, searchTerms, shapes, statusTones, tableDisplay, termMatches, unmarkFieldRefs, webhookResources };
package/dist/keys.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { FieldType, KeyValue, ResourceModel } from "./model.js";
2
2
  //#region src/keys.d.ts
3
+ /** The field types a primary key part may have: `integer`, `bigint`, `uuid` or `text`. */
3
4
  export type KeyType = Extract<FieldType, 'integer' | 'bigint' | 'uuid' | 'text'>;
4
5
  export declare const encodeKey: (key: KeyValue | readonly KeyValue[]) => string;
5
6
  export declare const decodeKey: (encoded: string, types: readonly KeyType[]) => string | number | (string | number)[];
package/dist/layout.d.ts CHANGED
@@ -2,10 +2,25 @@ import { LayoutItemModel, RelatedModel } from "./model.js";
2
2
  import { Ref } from "./refs.js";
3
3
  import { ComponentRef, ViewProps } from "./view-displays.js";
4
4
  //#region src/layout.d.ts
5
+ /**
6
+ * The items of a record page, for a view's `.layout((r) => [...])`, exported as `l`. See
7
+ * [The record page](website/src/content/docs/reference/ui-config.mdx#the-record-page).
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * view<typeof repairs>('repairs').layout((r) => [
12
+ * l.section('Repair', [r.bike, r.problem, r.status]),
13
+ * l.sidebar([r.booked_on, r.estimate]),
14
+ * l.related('Parts used', { resource: 'repair_parts', field: 'repair_id' }),
15
+ * ])
16
+ * ```
17
+ */
5
18
  export declare const layout: {
19
+ /** A titled group of fields in the main column, editable where the user may write; `help` is a line under the title. */
6
20
  section: (title: string, fields: Ref[], o?: {
7
21
  help?: string;
8
22
  }) => LayoutItemModel;
23
+ /** A read-only summary card of fields beside the main column. */
9
24
  sidebar: (fields: Ref[]) => LayoutItemModel;
10
25
  /** A table of the records of another resource that point at this one, directly or through a join table. */
11
26
  related: (title: string, o: Omit<RelatedModel, "kind" | "title">) => LayoutItemModel;
package/dist/layout.js CHANGED
@@ -1,13 +1,28 @@
1
1
  import { markFieldRefs } from "./field-ref.js";
2
2
  import { customComponent } from "./view-displays.js";
3
3
  //#region src/layout.ts
4
+ /**
5
+ * The items of a record page, for a view's `.layout((r) => [...])`, exported as `l`. See
6
+ * [The record page](website/src/content/docs/reference/ui-config.mdx#the-record-page).
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * view<typeof repairs>('repairs').layout((r) => [
11
+ * l.section('Repair', [r.bike, r.problem, r.status]),
12
+ * l.sidebar([r.booked_on, r.estimate]),
13
+ * l.related('Parts used', { resource: 'repair_parts', field: 'repair_id' }),
14
+ * ])
15
+ * ```
16
+ */
4
17
  const layout = {
18
+ /** A titled group of fields in the main column, editable where the user may write; `help` is a line under the title. */
5
19
  section: (title, fields, o = {}) => ({
6
20
  kind: "section",
7
21
  title,
8
22
  fields: fields.map((ref) => ref.name),
9
23
  ...o.help !== void 0 && { help: o.help }
10
24
  }),
25
+ /** A read-only summary card of fields beside the main column. */
11
26
  sidebar: (fields) => ({
12
27
  kind: "sidebar",
13
28
  fields: fields.map((ref) => ref.name)