@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
|
@@ -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)
|
|
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.
|
|
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
|
+
"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.
|
|
48
|
-
"@protobase/query": "0.68.
|
|
49
|
-
"@protobase/schema": "0.68.
|
|
50
|
-
"@protobase/workflow-plugins": "0.68.
|
|
51
|
-
"@protobase/workflows": "0.68.
|
|
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",
|