@protobase/schema 0.55.3 → 0.55.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/model.d.ts +10 -0
- package/dist/nav-recent.js +2 -1
- package/dist/open-existing-problems.js +16 -0
- package/dist/resource-model.d.ts +1 -0
- package/dist/resource-model.js +4 -1
- package/dist/resource.d.ts +12 -0
- package/dist/resource.js +14 -0
- package/package.json +1 -1
package/dist/model.d.ts
CHANGED
|
@@ -149,6 +149,11 @@ export type ResourceModel = {
|
|
|
149
149
|
comments?: true;
|
|
150
150
|
/** Whether open pages refresh as soon as its records change (`.live()`). */
|
|
151
151
|
live?: true;
|
|
152
|
+
/**
|
|
153
|
+
* The fields of a unique key whose conflict on create answers the record already holding those values, to a caller
|
|
154
|
+
* who may read it (`.openExisting()`).
|
|
155
|
+
*/
|
|
156
|
+
openExisting?: string[];
|
|
152
157
|
};
|
|
153
158
|
/** What happened to a record: `delete` and `undelete` include setting and clearing a soft delete field. */
|
|
154
159
|
export type EventOperation = 'create' | 'update' | 'delete' | 'undelete';
|
|
@@ -1118,6 +1123,11 @@ export type NavRecentModel = {
|
|
|
1118
1123
|
orderBy?: string;
|
|
1119
1124
|
/** How many records to show, 1 to 20; 3 when omitted. */
|
|
1120
1125
|
limit?: number;
|
|
1126
|
+
/**
|
|
1127
|
+
* Marks each record for the person reading, such as bold with a count of unread messages: the name of a hook in the
|
|
1128
|
+
* project UI's `marks`, which the sidebar calls in the browser. Presentation only: it is no field, filter or sort key.
|
|
1129
|
+
*/
|
|
1130
|
+
marks?: string;
|
|
1121
1131
|
};
|
|
1122
1132
|
/** Where a resource sits in the sidebar (`.nav(...)`); see [Sidebar](website/src/content/docs/reference/sidebar.md). */
|
|
1123
1133
|
export type NavModel = {
|
package/dist/nav-recent.js
CHANGED
|
@@ -32,7 +32,8 @@ const navRecentErrors = (recent, model) => [
|
|
|
32
32
|
...Object.entries(recent.tones ?? {}).filter(([, tone]) => !statusTones.includes(tone)).map(([value, tone]) => `tone "${tone}" for "${value}" is not one of ${statusTones.join(", ")}`),
|
|
33
33
|
...recent.limit === void 0 || Number.isInteger(recent.limit) && recent.limit >= 1 && recent.limit <= maxLimit ? [] : [`limit must be a whole number from 1 to ${maxLimit}`],
|
|
34
34
|
...recent.filter === void 0 ? [] : filterErrors(model, recent.filter).map((error) => `filter: ${error.message}`),
|
|
35
|
-
...recent.orderBy === void 0 ? [] : orderByErrors(model, recent.orderBy).map((error) => `orderBy: ${error.message}`)
|
|
35
|
+
...recent.orderBy === void 0 ? [] : orderByErrors(model, recent.orderBy).map((error) => `orderBy: ${error.message}`),
|
|
36
|
+
...recent.marks === void 0 || typeof recent.marks === "string" && recent.marks !== "" ? [] : ["marks needs the name of a hook in the project UI's marks"]
|
|
36
37
|
];
|
|
37
38
|
//#endregion
|
|
38
39
|
export { defaultRecentLimit, navRecentErrors, statusTones };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/open-existing-problems.ts
|
|
2
|
+
const openExistingProblems = (model) => {
|
|
3
|
+
const names = model.openExisting;
|
|
4
|
+
if (!names) return [];
|
|
5
|
+
if (names.length === 0) return ["openExisting names no field"];
|
|
6
|
+
return names.flatMap((name, index) => {
|
|
7
|
+
const field = model.fields[name];
|
|
8
|
+
return [
|
|
9
|
+
...field.encrypted ? ["is encrypted"] : [],
|
|
10
|
+
...field.file ? ["is a file field"] : [],
|
|
11
|
+
...names.indexOf(name) !== index ? ["is given twice"] : []
|
|
12
|
+
].map((problem) => `openExisting field "${name}" ${problem}`);
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { openExistingProblems };
|
package/dist/resource-model.d.ts
CHANGED
package/dist/resource-model.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promptFields } from "./ai-prompt.js";
|
|
2
2
|
import { buildEventModels } from "./events/event-models.js";
|
|
3
3
|
import { computedProblems } from "./computed/computed-problems.js";
|
|
4
|
+
import { openExistingProblems } from "./open-existing-problems.js";
|
|
4
5
|
import { snakeCase } from "./naming.js";
|
|
5
6
|
//#region src/resource-model.ts
|
|
6
7
|
const parseTable = (table) => {
|
|
@@ -75,7 +76,8 @@ const assembleModel = (state) => {
|
|
|
75
76
|
...state.comments && { comments: true },
|
|
76
77
|
...state.live && { live: true },
|
|
77
78
|
...state.position && { position: { ...state.position } },
|
|
78
|
-
...state.parents && { parents: state.parents.map((parent) => ({ ...parent })) }
|
|
79
|
+
...state.parents && { parents: state.parents.map((parent) => ({ ...parent })) },
|
|
80
|
+
...state.openExisting && { openExisting: [...state.openExisting] }
|
|
79
81
|
};
|
|
80
82
|
};
|
|
81
83
|
const sensitiveProblems = (model) => Object.values(model.fields).filter((field) => field.sensitive).flatMap((field) => [
|
|
@@ -168,6 +170,7 @@ const buildResourceModel = (state) => {
|
|
|
168
170
|
...positionProblems(model),
|
|
169
171
|
...parentProblems(model),
|
|
170
172
|
...aiProblems(model),
|
|
173
|
+
...openExistingProblems(model),
|
|
171
174
|
...computedProblems(model),
|
|
172
175
|
...events?.problems ?? []
|
|
173
176
|
];
|
package/dist/resource.d.ts
CHANGED
|
@@ -82,6 +82,18 @@ export declare class ResourceBuilder<F extends FieldsInput = {}, K = never> {
|
|
|
82
82
|
search(pick: (r: SearchRefs<F>) => SearchRef[]): ResourceBuilder<F, K>;
|
|
83
83
|
/** The field holding the owning user's id, which `.own` capability scopes filter on. */
|
|
84
84
|
owner(pick: (r: FieldRefs<F>) => Ref): ResourceBuilder<F, K>;
|
|
85
|
+
/**
|
|
86
|
+
* A unique key of the table, as its fields, whose conflict on create opens the record already holding those values:
|
|
87
|
+
* the API's 409 names that record's key (`existing.key`) to a caller who may read it, and the create form opens it.
|
|
88
|
+
* The fields must be exactly the columns of a unique index or constraint, such as one over a generated column. See
|
|
89
|
+
* [Opening an existing record](website/src/content/docs/reference/data-config.mdx#opening-an-existing-record).
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* .openExisting((r) => [r.organization_id, r.member_key])
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
openExisting(pick: (r: FieldRefs<F>) => Ref[]): ResourceBuilder<F, K>;
|
|
85
97
|
/**
|
|
86
98
|
* The field holding the id of the user who created the record, such as a chat message's sender: every create sets it
|
|
87
99
|
* to the signed-in user's id, and no request may write it, so it is never the client's word. A create by no user
|
package/dist/resource.js
CHANGED
|
@@ -84,6 +84,20 @@ var ResourceBuilder = class ResourceBuilder {
|
|
|
84
84
|
return this.next({ owner: pick(this.refs()).name });
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
|
+
* A unique key of the table, as its fields, whose conflict on create opens the record already holding those values:
|
|
88
|
+
* the API's 409 names that record's key (`existing.key`) to a caller who may read it, and the create form opens it.
|
|
89
|
+
* The fields must be exactly the columns of a unique index or constraint, such as one over a generated column. See
|
|
90
|
+
* [Opening an existing record](website/src/content/docs/reference/data-config.mdx#opening-an-existing-record).
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* .openExisting((r) => [r.organization_id, r.member_key])
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
openExisting(pick) {
|
|
98
|
+
return this.next({ openExisting: pick(this.refs()).map((ref) => ref.name) });
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
87
101
|
* The field holding the id of the user who created the record, such as a chat message's sender: every create sets it
|
|
88
102
|
* to the signed-in user's id, and no request may write it, so it is never the client's word. A create by no user
|
|
89
103
|
* leaves it empty.
|