@protobase/cli 0.66.11 → 0.66.13

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.
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.66.11";
2
+ var version = "0.66.13";
3
3
  //#endregion
4
4
  export { version };
@@ -22,5 +22,14 @@ const builtInModels = (config, models) => {
22
22
  views: [...webhooks.views, ...added.views].map((view) => view.toModel())
23
23
  };
24
24
  };
25
+ /**
26
+ * A missing index on a built-in table as a recommendation: the app owns its schema, so a database migrated by an earlier
27
+ * version still serves, and only the reads that need the index are refused until `protobase migration` writes it.
28
+ */
29
+ const builtInIndexIssues = (issues) => issues.map((issue) => ({
30
+ ...issue,
31
+ severity: "warning",
32
+ suggestion: `write it as a migration with \`protobase migration\` (${issue.suggestion})`
33
+ }));
25
34
  //#endregion
26
- export { builtInModels };
35
+ export { builtInIndexIssues, builtInModels };
@@ -3,7 +3,7 @@ import { connect } from "../db/connect.js";
3
3
  import { introspect } from "../db/introspect.js";
4
4
  import { loadDataConfig } from "../project/load-data-config.js";
5
5
  import { readOnlyDb } from "../db/read-only-db.js";
6
- import { builtInModels } from "./built-in-models.js";
6
+ import { builtInIndexIssues, builtInModels } from "./built-in-models.js";
7
7
  import { checkResource } from "./check.js";
8
8
  import { indexIssues } from "./index-issues.js";
9
9
  import { readShapes } from "./read-shapes.js";
@@ -28,7 +28,7 @@ const runDoctor = async (options, out) => {
28
28
  views: [...builtIn.views, ...config.views],
29
29
  pages: config.pages
30
30
  });
31
- const indexes = await Promise.all(models.map(async (model) => indexIssues(model, await tableIndexes(db, model), shapes))).finally(() => db.destroy());
31
+ const indexes = await Promise.all(models.map(async (model) => indexIssues(model, await tableIndexes(db, model), shapes))).then((found) => found.map((issues, i) => i < builtIn.models.length ? builtInIndexIssues(issues) : issues)).finally(() => db.destroy());
32
32
  const issues = models.flatMap((model, i) => [
33
33
  ...checkResource(model, tables),
34
34
  ...relationIssues(model, models),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/cli",
3
- "version": "0.66.11",
3
+ "version": "0.66.13",
4
4
  "description": "The protobase command: scaffold, doctor, dev, build and serve a Protobase project.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -43,12 +43,12 @@
43
43
  "dependencies": {
44
44
  "@better-auth/core": "^1.7.12",
45
45
  "@hono/node-server": "^2.1.3",
46
- "@protobase/config": "0.66.11",
47
- "@protobase/layout": "0.66.11",
48
- "@protobase/query": "0.66.11",
49
- "@protobase/schema": "0.66.11",
50
- "@protobase/server": "0.66.11",
51
- "@protobase/ui": "0.66.11",
46
+ "@protobase/config": "0.66.13",
47
+ "@protobase/layout": "0.66.13",
48
+ "@protobase/query": "0.66.13",
49
+ "@protobase/schema": "0.66.13",
50
+ "@protobase/server": "0.66.13",
51
+ "@protobase/ui": "0.66.13",
52
52
  "@react-email/render": "^2.1.0",
53
53
  "@scalar/hono-api-reference": "^0.12.10",
54
54
  "@sentry/vite-plugin": "^11.10.0",
@@ -24,5 +24,4 @@ React components, field types, pages and handlers of your own, loaded as plugins
24
24
  - [Plugin settings](../reference/plugins.md#loading): Plugins are loaded from the config, limited to roles and given settings.
25
25
  - [Plugin fallbacks](../reference/plugins.md#when-a-plugin-is-off): A plugin that fails or does not fit the version is turned off alone, and admins see why.
26
26
  - [Before sign-in](../reference/plugins.md#before-sign-in): A plugin can run around the sign-in page, for example to sign someone in from a link.
27
- - [Confirm it's you](../reference/plugins.md#api): The app's step that has the person confirm it's them, and its field for a hidden value that asks for it, for your own pages.
28
27
  - [Unstable modules](../reference/plugins.md#the-unstable-entry): UI with its own build imports any module of the app's UI, without a promise that it stays the same, instead of copying it.
@@ -107,7 +107,7 @@ protobase doctor [connection string | --env VAR] [--config <dir>]
107
107
 
108
108
  The URL comes as for [`scaffold`](#scaffold): the connection string, the variable `--env` names, or `DATABASE_URL`, each also read from the nearest `.env`.
109
109
 
110
- Imports `config/index.ts` and the views of `config/*/ui.ts`, as the config module has them by convention, and checks every exported resource against the database, with the resources Protobase adds by what `protobase.config.ts` (read with `command: 'tool'`) and the resources enable: the [webhook](webhooks.md#subscriptions-in-the-admin-app) ones of `webhooks`, Failed jobs, [Activity](history.md) and [Comments](comments.md). The tables [`migration`](#migration) writes for those have every index their reads need, so after the project's migrations they pass:
110
+ Imports `config/index.ts` and the views of `config/*/ui.ts`, as the config module has them by convention, and checks every exported resource against the database, with the resources Protobase adds by what `protobase.config.ts` (read with `command: 'tool'`) and the resources enable: the [webhook](webhooks.md#subscriptions-in-the-admin-app) ones of `webhooks`, Failed jobs, [Activity](history.md) and [Comments](comments.md). The tables [`migration`](#migration) writes for those have every index their reads need, so after the project's migrations they pass; a read of theirs that lacks an index, as on a table an earlier version wrote, is a warning to run `migration`, since the app owns its schema:
111
111
 
112
112
  - error: missing table or column, field type that does not fit the column (a file field needs a text column), table without a usable key, configured key not backed by a unique index, `.openExisting()` fields that are not the columns of a unique index, relation to a resource the config does not declare
113
113
  - error: a read the [scan guard](api.md#safety) refuses, because no index serves a column it filters, sorts, searches or counts by. Doctor reads each table's indexes from the catalog, as the server does, and judges with the scan guard's own rule every read the API takes and the app makes: a filter on each `.filterable()` field, a sort by each `.sortable()` one, `search()` over the search fields, a role's own records (`.owner()`) and the names a relation shows; each view's list in its order and with the filter it opens with, its filter widgets and their counts, its chart, its map, board, calendar and timeline, its card photos, its order by hand, its related sections, galleries and charts, its named lists, its recent records and a saved search's new records; and each block of a [composed page](layouts.md) that lists records, and each `Chart` block's grouped and split fields. Each error is an index to add, with every request that needs it and where it comes from:
@@ -64,7 +64,7 @@ Once a resource takes comments, admins get **Comments** (the built-in resource `
64
64
 
65
65
  ## The table
66
66
 
67
- [`protobase migration`](cli.md#migration) adds the schema `comments` with the table `comments.comments`; apply it with the project's other migrations. It has an index for each column the Comments list filters on, and the next migration adds one an earlier version's table lacks. `protobase dev` and `protobase serve` do not start while a resource has comments and the table or one of its indexes is missing. A deleted record's comments stay in the table.
67
+ [`protobase migration`](cli.md#migration) adds the schema `comments` with the table `comments.comments`; apply it with the project's other migrations. It has an index for each column the Comments list filters on, and the next migration adds one an earlier version's table lacks. `protobase dev` and `protobase serve` do not start while a resource has comments and the table is missing; without an index added since, they start, and only the Comments list's reads that need it are refused. A deleted record's comments stay in the table.
68
68
 
69
69
  | Column | |
70
70
  | --- | --- |
@@ -71,7 +71,7 @@ Once a resource has history, admins get **Activity** (the built-in resource `rec
71
71
 
72
72
  ## The table
73
73
 
74
- [`protobase migration`](cli.md#migration) adds the table `changes.history` to the `changes` schema of the event capture (renamed with `events: { schema }`), and the capture triggers of each resource with history; apply it with the project's other migrations. It has an index for each column the Activity list filters on, and the next migration adds one an earlier version's table lacks. `protobase dev` and `protobase serve` do not start while the table, one of its indexes or a trigger is missing. A resource that drops `.history()` loses its triggers, unless it has events, at the next migration; its changes stay in the table.
74
+ [`protobase migration`](cli.md#migration) adds the table `changes.history` to the `changes` schema of the event capture (renamed with `events: { schema }`), and the capture triggers of each resource with history; apply it with the project's other migrations. It has an index for each column the Activity list filters on, and the next migration adds one an earlier version's table lacks. `protobase dev` and `protobase serve` do not start while the table or a trigger is missing; without an index added since, they start, and only the Activity list's reads that need it are refused. A resource that drops `.history()` loses its triggers, unless it has events, at the next migration; its changes stay in the table.
75
75
 
76
76
  | Column | |
77
77
  | --- | --- |
@@ -335,8 +335,6 @@ From `@protobase/ui`:
335
335
  | `FieldWidget`, `FieldWidgetProps`, `FieldWidgetEditorProps` | The types of a [field type](#field-types) and of its parts' props. |
336
336
  | `RecordCardProps` | The props of a [record card](custom-components.md#record-cards), `{ row }`. |
337
337
  | `AuthLayout`, `CodeForm`, `ResendCodeButton`, `Button`, `buttonClass`, `Input`, `Spinner`, `LogoMark` | The pieces of the app's sign-in pages, for a page of a plugin or a host's own that looks like them. Outside the app, `@protobase/ui/styles.css` is the stylesheet that draws them, for a Vite build with Tailwind. |
338
- | `ConfirmSignIn`, `ConfirmSignInProps` | The app's step that asks the person to confirm it's them, with a passkey, a code or their password, after the server refused something for want of a recent strong sign-in; `onConfirmed` is called once they did, to ask again. |
339
- | `SensitiveField`, `SensitiveFieldProps` | The app's field for a value hidden like a password, which shows a stored one only once the person asks for it, confirming it's them first when the server wants that. |
340
338
  | `isFramed`, `useArmedAfterFocus`, `useGuardedPress`, `allowDelayMs` | The connect page's guard against clickjacking and click-through, for a host's own consent screen: it refuses to render when `isFramed()`, and its Allow button spreads `useGuardedPress(armed, onAllow)`, so a press counts only once the page has been in front for `allowDelayMs`, and a press anywhere on the page before then starts that wait again. |
341
339
  | `pluginApi` | The plugin API of the app's `@protobase/ui`. |
342
340
  | `protobaseVersion` | The Protobase version of the app's `@protobase/ui`. |
@@ -116,7 +116,7 @@ It adds two pages, over a `webhooks` schema that [`protobase migration`](cli.md#
116
116
  - **Webhook subscriptions** (`webhook_subscriptions`, the table `webhooks.subscriptions`): a name, the events (`orders.created orders.large`, or `orders.*`), the URL, a filter, extra headers, full or thin payload, and whether it is enabled. The server sets the tenant and the owner, the person who made it, and makes the secret, which only a [reveal](api.md#sensitive-fields-and-audit) shows. Saving checks the events and the filter against the resources, and refuses a URL whose host is a private, loopback or link-local address.
117
117
  - **Webhook deliveries** (`webhook_deliveries`, a view over the delivery jobs): the deliveries that wait for their next try or failed for good, with their last error. A delivery leaves the list once it succeeds.
118
118
 
119
- The migration gives the subscriptions table an index for each sort, filter and search of its list, and creates the `pg_trgm` extension the search's indexes need (`create extension if not exists pg_trgm`, a trusted extension since Postgres 13, so any role that may create in the database can). A database that has an earlier version's schema gets the indexes from the next `protobase migration`; the server does not start until it is applied.
119
+ The migration gives the subscriptions table an index for each sort, filter and search of its list, and creates the `pg_trgm` extension the search's indexes need (`create extension if not exists pg_trgm`, a trusted extension since Postgres 13, so any role that may create in the database can). A database that has an earlier version's schema gets the indexes from the next `protobase migration`; until it is applied the server still starts, and refuses only the list's reads that need them.
120
120
 
121
121
  Both are scoped to the tenant like any resource with `.tenant()`, and their access decides who may do what: `webhook_subscriptions.create`, `webhook_deliveries.update` and so on, as for the app's own resources. A role's wildcard over resources, such as `*.read`, grants none of them: their URLs and secrets let whoever reads them call the receivers, so with roles only admins (`*`) and roles that [name them](access.md#resources-that-need-named-grants) manage webhook subscriptions.
122
122