@protobase/client 0.14.0 → 0.14.2

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/client.d.ts CHANGED
@@ -57,6 +57,7 @@ export declare const createClient: (options?: ClientOptions) => {
57
57
  facets: (resource: ResourceRef, field: string, o?: {
58
58
  filter?: FilterInput;
59
59
  limit?: number;
60
+ label?: string;
60
61
  }) => Promise<Facet[]>;
61
62
  series: (resource: ResourceRef, params: SeriesParams & {
62
63
  filter?: FilterInput;
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
- import { filterText, listWire, queryString } from "./query-string.js";
2
- import { originOf, withFileOrigin } from "./file-urls.js";
1
+ import { filterText, labelEntries, listWire, photosWire, queryString } from "./query-string.js";
2
+ import { originOf, photosWithOrigin, withFileOrigin } from "./file-urls.js";
3
3
  import { createTransport } from "./transport.js";
4
4
  import { fetchWithProgress } from "./upload-request.js";
5
5
  import { encodeKey } from "@protobase/schema/internal";
@@ -12,6 +12,8 @@ const toPage = (body, response, origin) => ({
12
12
  totalSizeEstimate: body.total_size_estimate,
13
13
  ...body.prev_page_token !== void 0 && { prevPageToken: body.prev_page_token },
14
14
  ...body.total_size !== void 0 && { totalSize: body.total_size },
15
+ ...body.labels !== void 0 && { labels: body.labels },
16
+ ...body.photos !== void 0 && { photos: photosWithOrigin(body.photos, origin) },
15
17
  ...response.headers.get("x-protobase-warning") && { warning: response.headers.get("x-protobase-warning") }
16
18
  });
17
19
  const etagOf = (response) => response.headers.get("etag") ?? "";
@@ -61,7 +63,8 @@ const createClient = (options = {}) => {
61
63
  path: `/${nameOf(resource)}:search`,
62
64
  body: {
63
65
  ...wire,
64
- fields: params?.fields
66
+ fields: params?.fields,
67
+ labels: labelEntries(params?.labels)
65
68
  }
66
69
  });
67
70
  return toPage(await response.json(), response, origin);
@@ -136,6 +139,7 @@ const createClient = (options = {}) => {
136
139
  });
137
140
  return batchResultOf(await response.json(), origin);
138
141
  };
142
+ /** `label` names a relation's values by that field of the records they point at, as a list's `labels` does. */
139
143
  const facets = async (resource, field, o = {}) => {
140
144
  return (await (await send({
141
145
  method: "GET",
@@ -143,7 +147,8 @@ const createClient = (options = {}) => {
143
147
  query: queryString({
144
148
  field,
145
149
  filter: filterText(o.filter) || void 0,
146
- limit: o.limit
150
+ limit: o.limit,
151
+ label: o.label
147
152
  })
148
153
  })).json()).facets;
149
154
  };
@@ -193,13 +198,17 @@ const createClient = (options = {}) => {
193
198
  zoom: params.zoom,
194
199
  filter: filterText(params.filter) || void 0,
195
200
  order_by: params.orderBy,
196
- fields: params.fields?.join(",")
201
+ fields: params.fields?.join(","),
202
+ labels: labelEntries(params.labels)?.join(","),
203
+ ...photosWire(params.photos)
197
204
  })
198
205
  })).json();
199
206
  return {
200
207
  items: body.items.map((item) => withFileOrigin(item, origin)),
201
208
  buckets: body.buckets,
202
- totalSize: body.total_size
209
+ totalSize: body.total_size,
210
+ ...body.labels !== void 0 && { labels: body.labels },
211
+ ...body.photos !== void 0 && { photos: photosWithOrigin(body.photos, origin) }
203
212
  };
204
213
  };
205
214
  /** The page that starts at row `position` of a sort (scrollbar jumps), with the tokens of its own neighbours. Past the end it is empty. */
package/dist/file-urls.js CHANGED
@@ -24,6 +24,8 @@ const withFileOrigin = (record, origin) => {
24
24
  if (origin === void 0 || typeof record !== "object" || record === null) return record;
25
25
  return Object.fromEntries(Object.entries(record).map(([name, value]) => [name, isFileAtPath(value) ? fromOrigin(value, origin) : value]));
26
26
  };
27
+ /** Each record's photos, by key, every file downloading from `origin`, as `withFileOrigin` makes a record's. */
28
+ const photosWithOrigin = (photos, origin) => origin === void 0 ? photos : Object.fromEntries(Object.entries(photos).map(([key, files]) => [key, files.map((file) => isFileAtPath(file) ? fromOrigin(file, origin) : file)]));
27
29
  /**
28
30
  * The link of a stored file, or of its variant by that name when it has one (`fileUrl(listing.photo, 'card')`); the
29
31
  * file's own link otherwise, and `undefined` for a missing file or one without a link.
@@ -33,4 +35,4 @@ const fileUrl = (file, variant) => {
33
35
  return (variant === void 0 ? void 0 : file.variants?.[variant]?.url) ?? file.url;
34
36
  };
35
37
  //#endregion
36
- export { fileUrl, originOf, withFileOrigin };
38
+ export { fileUrl, originOf, photosWithOrigin, withFileOrigin };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FilterInput, ListParams, MapParams, filterText, listWire } from "./query-string.js";
2
2
  import { ClientOptions } from "./transport.js";
3
3
  import { UploadProgress } from "./upload-request.js";
4
- import { BatchOp, BatchRef, BatchResult, Facet, Histogram, HistogramBucket, ListPage, MapBounds, MapBucket, MapResult, Meta, MetaResult, PluginRef, RecordOf, RecordPermissions, ResourcePermissions, ResourceRef, Series, SeriesParams, SeriesPoint, SourceRef, Stored, StoredFile, StoredFileVariant } from "./types.js";
4
+ import { BatchOp, BatchRef, BatchResult, Facet, Histogram, HistogramBucket, ListPage, MapBounds, MapBucket, MapResult, Meta, MetaResult, PluginRef, RecordOf, RecordPermissions, RecordPhotos, RelatedLabels, ResourcePermissions, ResourceRef, Series, SeriesParams, SeriesPoint, SourceRef, Stored, StoredFile, StoredFileVariant } from "./types.js";
5
5
  import { Client, InvokeOptions, UploadOptions, UploadResult, createClient } from "./client.js";
6
6
  import { ApiError, PreconditionFailedError, ProblemDetails, ProblemError, isApiError } from "./problem.js";
7
7
  import { fileUrl } from "./file-urls.js";
@@ -18,4 +18,4 @@ import { AuthSession, AuthSessionOptions, createAuthSession, tokenExpiry } from
18
18
  import { createStaticSession } from "./static-session.js";
19
19
  import { AssistantClient, AssistantClientOptions, AssistantConnection, createAssistantClient } from "./assistant.js";
20
20
  import { RuntimeClient, RuntimeClientOptions, RuntimePolicy, RuntimeStatus, createRuntimeClient } from "./runtime.js";
21
- export { type AccountSecurity, type AccountSignIn, type ActiveRole, ApiError, type AssistantClient, type AssistantClientOptions, type AssistantConnection, AuthError, type AuthSession, type AuthSessionOptions, type AuthUser, type AuthenticatorSetup, type BatchOp, type BatchRef, type BatchResult, type Client, type ClientOptions, type CurrentOrganization, type Facet, type FilterInput, type Histogram, type HistogramBucket, type InvitationPreview, type InvitationSent, type InvokeOptions, type ListPage, type ListParams, type MapBounds, type MapBucket, type MapParams, type MapResult, type Meta, type MetaResult, type Organization, type OrganizationInvitation, type OrganizationMember, type OrganizationRole, type OrganizationsClient, type Passkey, type PlatformSignIn, type PluginRef, PreconditionFailedError, type ProblemDetails, type ProblemError, type RecordOf, type RecordPermissions, type RequiredSetup, type ResourcePermissions, type ResourceRef, type RoleLabel, type RoleOption, type RolesClient, type RuntimeClient, type RuntimeClientOptions, type RuntimePolicy, type RuntimeStatus, type Series, type SeriesParams, type SeriesPoint, type SetupStatus, type SignInMethod, type SignInPolicy, type SignInPolicyClient, type SignInPolicyState, type SignInResult, type SignInRule, type SourceMeta, type SourceRef, type StaffAccessRule, type StaffSignIn, type StaffSignInClient, type Stored, type StoredFile, type StoredFileVariant, type TwoFactorMethod, type UploadOptions, type UploadProgress, type UploadResult, createAssistantClient, createAuthSession, createClient, createRuntimeClient, createStaticSession, fileUrl, filterText, isApiError, listWire, routedClient, sourceMeta, tokenExpiry };
21
+ export { type AccountSecurity, type AccountSignIn, type ActiveRole, ApiError, type AssistantClient, type AssistantClientOptions, type AssistantConnection, AuthError, type AuthSession, type AuthSessionOptions, type AuthUser, type AuthenticatorSetup, type BatchOp, type BatchRef, type BatchResult, type Client, type ClientOptions, type CurrentOrganization, type Facet, type FilterInput, type Histogram, type HistogramBucket, type InvitationPreview, type InvitationSent, type InvokeOptions, type ListPage, type ListParams, type MapBounds, type MapBucket, type MapParams, type MapResult, type Meta, type MetaResult, type Organization, type OrganizationInvitation, type OrganizationMember, type OrganizationRole, type OrganizationsClient, type Passkey, type PlatformSignIn, type PluginRef, PreconditionFailedError, type ProblemDetails, type ProblemError, type RecordOf, type RecordPermissions, type RecordPhotos, type RelatedLabels, type RequiredSetup, type ResourcePermissions, type ResourceRef, type RoleLabel, type RoleOption, type RolesClient, type RuntimeClient, type RuntimeClientOptions, type RuntimePolicy, type RuntimeStatus, type Series, type SeriesParams, type SeriesPoint, type SetupStatus, type SignInMethod, type SignInPolicy, type SignInPolicyClient, type SignInPolicyState, type SignInResult, type SignInRule, type SourceMeta, type SourceRef, type StaffAccessRule, type StaffSignIn, type StaffSignInClient, type Stored, type StoredFile, type StoredFileVariant, type TwoFactorMethod, type UploadOptions, type UploadProgress, type UploadResult, createAssistantClient, createAuthSession, createClient, createRuntimeClient, createStaticSession, fileUrl, filterText, isApiError, listWire, routedClient, sourceMeta, tokenExpiry };
@@ -1,4 +1,4 @@
1
- import { FilterExpr } from "@protobase/schema";
1
+ import { CardPhotosModel, FilterExpr } from "@protobase/schema";
2
2
  //#region src/query-string.d.ts
3
3
  export type FilterInput = string | FilterExpr;
4
4
  export type ListParams = {
@@ -8,6 +8,17 @@ export type ListParams = {
8
8
  pageSize?: number;
9
9
  pageToken?: string;
10
10
  fields?: string[];
11
+ /**
12
+ * Names the records relations point at, in the same answer: `{ place_id: 'name' }` gives each place's `name` in the
13
+ * page's `labels`. A record the caller cannot list, or whose field they cannot read, has no name there.
14
+ */
15
+ labels?: Record<string, string>;
16
+ /**
17
+ * Brings each record's first photos in the same answer, as a cards display's `photos` names them: the `image` of the
18
+ * records of `resource` whose relation `field` points at it, in `sort` order, at most ten. The caller gets those they
19
+ * could list themselves.
20
+ */
21
+ photos?: CardPhotosModel;
11
22
  count?: 'exact';
12
23
  };
13
24
  /** What `map` asks for: the fields of the position, the map's zoom, and the bounding box in `filter`. */
@@ -18,15 +29,22 @@ export type MapParams = {
18
29
  filter?: FilterInput;
19
30
  orderBy?: string;
20
31
  fields?: string[];
32
+ /** As a list's `labels`. */
33
+ labels?: Record<string, string>;
34
+ /** As a list's `photos`. */
35
+ photos?: CardPhotosModel;
21
36
  };
22
37
  export declare const filterText: (filter: FilterInput | undefined) => string | undefined;
23
38
  /** The snake_case parameters of `GET /{resource}` and the body of `POST /{resource}:search`. */
24
39
  export declare const listWire: (params?: ListParams) => {
40
+ count: "exact" | undefined;
41
+ photos: string | undefined;
42
+ photos_order_by: string | undefined;
25
43
  filter: string | undefined;
26
44
  order_by: string | undefined;
27
45
  page_size: number | undefined;
28
46
  page_token: string | undefined;
29
47
  fields: string | undefined;
30
- count: "exact" | undefined;
48
+ labels: string | undefined;
31
49
  };
32
50
  //#endregion
@@ -1,6 +1,16 @@
1
1
  import { printFilter } from "@protobase/schema";
2
2
  //#region src/query-string.ts
3
3
  const filterText = (filter) => typeof filter === "string" ? filter : filter && printFilter(filter);
4
+ /** `labels` as the API takes it: `relation.field` entries. */
5
+ const labelEntries = (labels) => {
6
+ const entries = Object.entries(labels ?? {}).map(([relation, field]) => `${relation}.${field}`);
7
+ return entries.length > 0 ? entries : void 0;
8
+ };
9
+ /** `photos` as the API takes it: a `resource.field.image` entry and the order of the photos. */
10
+ const photosWire = (photos) => ({
11
+ photos: photos && `${photos.resource}.${photos.field}.${photos.image}`,
12
+ photos_order_by: photos?.sort
13
+ });
4
14
  /** The snake_case parameters of `GET /{resource}` and the body of `POST /{resource}:search`. */
5
15
  const listWire = (params = {}) => ({
6
16
  filter: filterText(params.filter) || void 0,
@@ -8,6 +18,8 @@ const listWire = (params = {}) => ({
8
18
  page_size: params.pageSize,
9
19
  page_token: params.pageToken || void 0,
10
20
  fields: params.fields?.join(","),
21
+ labels: labelEntries(params.labels)?.join(","),
22
+ ...photosWire(params.photos),
11
23
  count: params.count
12
24
  });
13
25
  const queryString = (wire) => {
@@ -17,4 +29,4 @@ const queryString = (wire) => {
17
29
  return text ? `?${text}` : "";
18
30
  };
19
31
  //#endregion
20
- export { filterText, listWire, queryString };
32
+ export { filterText, labelEntries, listWire, photosWire, queryString };
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { BottomBarModel, InferRecord, ResourceModel, UserMenuModel, ViewModel } from "@protobase/schema";
1
+ import { BottomBarModel, InferRecord, ResourceModel, SignInViewModel, UserMenuModel, ViewModel } from "@protobase/schema";
2
2
  import { PageModel } from "@protobase/layout";
3
3
  //#region src/types.d.ts
4
4
  /** A resource by name, or the builder from `resource(...)`, which carries its record type. */
@@ -10,6 +10,10 @@ export type ResourceRef = string | {
10
10
  export type RecordOf<R extends ResourceRef> = R extends {
11
11
  readonly $fields: unknown;
12
12
  } ? InferRecord<R> : Record<string, unknown>;
13
+ /** Per relation, the names of the records it points at, by key as text; a record without one is absent. */
14
+ export type RelatedLabels = Record<string, Record<string, string>>;
15
+ /** Per record, by key as text, the files of its first photos in their order; a record without any is absent. */
16
+ export type RecordPhotos = Record<string, StoredFile[]>;
13
17
  export type ListPage<T> = {
14
18
  items: T[];
15
19
  /** `""` on the last page. */
@@ -19,12 +23,18 @@ export type ListPage<T> = {
19
23
  totalSizeEstimate: number;
20
24
  /** Only with `count: 'exact'`. */
21
25
  totalSize?: number;
26
+ /** Only with `labels`: per relation, the names of the records it points at, by key as text. */
27
+ labels?: RelatedLabels;
28
+ /** Only with `photos`: each record's first photos, by key as text. */
29
+ photos?: RecordPhotos;
22
30
  /** `X-Protobase-Warning`, for example a scan-guard notice. */
23
31
  warning?: string;
24
32
  };
33
+ /** `label`: with the `label` option, the name of the record a relation's value points at, when the caller may read it. */
25
34
  export type Facet = {
26
35
  value: string | number | boolean | null;
27
36
  count: number;
37
+ label?: string;
28
38
  };
29
39
  export type SeriesPoint = {
30
40
  bucket: string;
@@ -73,6 +83,8 @@ export type MapResult<T> = {
73
83
  items: T[];
74
84
  buckets: MapBucket[];
75
85
  totalSize: number;
86
+ labels?: RelatedLabels;
87
+ photos?: RecordPhotos;
76
88
  };
77
89
  /** What the signed-in user may do with a resource; `conditional` operations are decided per record by the server. */
78
90
  export type ResourcePermissions = {
@@ -85,6 +97,7 @@ export type ResourcePermissions = {
85
97
  /**
86
98
  * `assistant`: the assistant backend, for a caller with the `admin` or `ai` role when the app has one.
87
99
  * `runtime`: the runtime updates endpoint, for a caller with the `admin` role when the app has one.
100
+ * `signIn`: for a visitor who is not signed in, the resources they could use once signed in, with what to tell them.
88
101
  * `bottomBar`: the tabs on phones, of the bottom bar that names the caller's active role.
89
102
  * `plugins`: the plugins the admin app loads for the caller, each by its plugin.json.
90
103
  * `sources`: the other APIs whose resources the admin app draws for the caller.
@@ -95,6 +108,7 @@ export type Meta = {
95
108
  pages?: PageModel[];
96
109
  permissions?: Record<string, ResourcePermissions>;
97
110
  userMenu?: UserMenuModel;
111
+ signIn?: SignInViewModel[];
98
112
  bottomBar?: Omit<BottomBarModel, 'roles'>;
99
113
  assistant?: {
100
114
  url: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/client",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "description": "Typed fetch client for the Protobase REST API.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -30,8 +30,8 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@better-auth/passkey": "^1.7.7",
33
- "@protobase/layout": "0.14.0",
34
- "@protobase/schema": "0.14.0",
33
+ "@protobase/layout": "0.14.2",
34
+ "@protobase/schema": "0.14.2",
35
35
  "@simplewebauthn/browser": "^13.3.0",
36
36
  "better-auth": "^1.7.7"
37
37
  }