@protobase/server 0.68.3 → 0.68.5

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/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.68.3";
2
+ var version = "0.68.5";
3
3
  //#endregion
4
4
  export { version };
@@ -42,7 +42,7 @@ const definitionsResources = ({ roles, taken, organizations = false }) => {
42
42
  };
43
43
  const tables = resource(tablesResourceName).table(`${definitionsSchema}.tables`).fields({
44
44
  id: f.bigint().readOnly().dbDefault().filterable().sortable(),
45
- name: f.text().access(createOnly).filterable().sortable(),
45
+ name: f.text().access(createOnly),
46
46
  singular_label: f.text().max(maxLabelLength),
47
47
  plural_label: f.text().max(maxLabelLength),
48
48
  title_field: f.text().optional(),
@@ -51,7 +51,7 @@ const definitionsResources = ({ roles, taken, organizations = false }) => {
51
51
  ...organization
52
52
  }).primaryKey((r) => r.id).explicitGrants().access(accessOf(roles, organizations)).validate((table) => [...issue("name", nameIssue(table.name)), ...issue("title_field", table.title_field ? nameProblem(table.title_field, "field") : void 0)]);
53
53
  const fields = resource(fieldsResourceName).table(`${definitionsSchema}.fields`).fields({
54
- table_id: f.relation(tablesResourceName).access(createOnly).filterable(),
54
+ table_id: f.relation(tablesResourceName).access(createOnly).filterable().sortable(),
55
55
  name: f.text().access(createOnly),
56
56
  label: f.text().max(maxLabelLength),
57
57
  type: f.enum(definitionFieldTypes).access(createOnly),
@@ -30,7 +30,7 @@ const tablesView = view(tablesResourceName).names({
30
30
  title_field: r.title_field.label("Title field").notOnCreate().help("The name of the text field that titles each record and that search looks in.")
31
31
  })).list((r) => ({
32
32
  columns: [r.plural_label, r.name],
33
- sort: [[r.name, "asc"]]
33
+ sort: [[r.id, "asc"]]
34
34
  })).layout((r) => [l.section("Table", [
35
35
  r.plural_label,
36
36
  r.singular_label,
@@ -82,7 +82,7 @@ const fieldsView = view(fieldsResourceName).names({
82
82
  r.type,
83
83
  r.position
84
84
  ],
85
- sort: [[r.position, "asc"]]
85
+ sort: [[r.table_id, "asc"], [r.position, "asc"]]
86
86
  })).layout((r) => [l.section("Field", [
87
87
  r.table_id,
88
88
  r.label,
@@ -46,6 +46,11 @@ const fieldsSql = () => `create table ${definitionsSchema}.fields (
46
46
  check ((type = 'decimal') = (precision is not null and scale is not null))
47
47
  )`;
48
48
  /**
49
+ * Serves a table's fields in position order, the order its own fields take: the admin's scan guard accepts a sort on
50
+ * `position` only from an index that reaches it with `table_id` pinned. It also reaches a fields table made before it.
51
+ */
52
+ const fieldsPositionIndexSql = () => `create index if not exists fields_position_idx on ${definitionsSchema}.fields (table_id, position)`;
53
+ /**
49
54
  * Brings a definitions table made before organizations to the shape of `tablesSql`: a name unique per organization and
50
55
  * the served name.
51
56
  */
@@ -65,4 +70,4 @@ const schemasSql = () => [
65
70
  `grant usage, create on schema ${userTablesSchema} to current_user`
66
71
  ];
67
72
  //#endregion
68
- export { fieldsOrganizationSql, fieldsSql, nameIndexesSql, organizationsSql, schemasSql, tablesSql, versionDefaultSql };
73
+ export { fieldsOrganizationSql, fieldsPositionIndexSql, fieldsSql, nameIndexesSql, organizationsSql, schemasSql, tablesSql, versionDefaultSql };
@@ -1,15 +1,16 @@
1
1
  import { migrationCommand } from "../changes/capture-schema.js";
2
2
  import { definitionsSchema, userTablesSchema } from "./names.js";
3
- import { fieldsOrganizationSql, fieldsSql, nameIndexesSql, organizationsSql, schemasSql, tablesSql, versionDefaultSql } from "./schema-sql.js";
3
+ import { fieldsOrganizationSql, fieldsPositionIndexSql, fieldsSql, nameIndexesSql, organizationsSql, schemasSql, tablesSql, versionDefaultSql } from "./schema-sql.js";
4
4
  import { sql } from "kysely";
5
5
  //#region src/user-tables/schema.ts
6
- const current = (found) => found.tables && found.versionDefault && found.organizations && found.fields && found.data && found.trgm;
6
+ const current = (found) => found.tables && found.versionDefault && found.organizations && found.fields && found.positionIndex && found.data && found.trgm;
7
7
  const readUserTablesSchema = async (db) => {
8
8
  const { rows } = await sql`select
9
9
  to_regclass(${`${definitionsSchema}.tables`}) is not null as tables,
10
10
  exists (select from information_schema.columns where table_schema = ${definitionsSchema} and table_name = 'tables' and column_name = 'version' and column_default is not null) as "versionDefault",
11
11
  exists (select from information_schema.columns where table_schema = ${definitionsSchema} and table_name = 'tables' and column_name = 'table_name') as organizations,
12
12
  to_regclass(${`${definitionsSchema}.fields`}) is not null as fields,
13
+ to_regclass(${`${definitionsSchema}.fields_position_idx`}) is not null as "positionIndex",
13
14
  exists (select from pg_namespace where nspname = ${userTablesSchema}) as data,
14
15
  exists (select from pg_extension where extname = 'pg_trgm') as trgm`.execute(db);
15
16
  return rows[0];
@@ -27,14 +28,15 @@ const userTablesMigration = async (db) => {
27
28
  return `${[
28
29
  ...schemasSql(),
29
30
  ...tables,
30
- ...fields
31
+ ...fields,
32
+ fieldsPositionIndexSql()
31
33
  ].join(";\n\n")};`;
32
34
  };
33
35
  /** Refuses to go on while the schemas of user tables are missing; the project's migrations add them. */
34
36
  const checkUserTablesSchema = async (db) => {
35
37
  const found = await readUserTablesSchema(db);
36
38
  if (current(found)) return;
37
- throw new Error(`The ${definitionsSchema} or ${userTablesSchema} schema, the default of a definition's version, a definition's organization, or pg_trgm, is missing, and userTables keeps the tables users add there. Write it as a migration with \`${migrationCommand}\`, apply it with the project's migrations, then start again.`);
39
+ throw new Error(`The ${definitionsSchema} or ${userTablesSchema} schema, the default of a definition's version, a definition's organization, the position index of its fields, or pg_trgm, is missing, and userTables keeps the tables users add there. Write it as a migration with \`${migrationCommand}\`, apply it with the project's migrations, then start again.`);
38
40
  };
39
41
  //#endregion
40
42
  export { checkUserTablesSchema, userTablesMigration };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.68.3",
3
+ "version": "0.68.5",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -44,11 +44,11 @@
44
44
  "@better-auth/sso": "^1.7.12",
45
45
  "@livekit/protocol": "1.53.1",
46
46
  "@modelcontextprotocol/server": "^2.3.1",
47
- "@protobase/layout": "0.68.3",
48
- "@protobase/query": "0.68.3",
49
- "@protobase/schema": "0.68.3",
50
- "@protobase/workflow-plugins": "0.68.3",
51
- "@protobase/workflows": "0.68.3",
47
+ "@protobase/layout": "0.68.5",
48
+ "@protobase/query": "0.68.5",
49
+ "@protobase/schema": "0.68.5",
50
+ "@protobase/workflow-plugins": "0.68.5",
51
+ "@protobase/workflows": "0.68.5",
52
52
  "@react-email/render": "^2.1.0",
53
53
  "@react-pdf/primitives": "^4.4.0",
54
54
  "@react-pdf/renderer": "^4.9.0",