@adula/kit 0.2.0-alpha.4 → 1.2.0
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/README.md +12 -2
- package/build/agent/AGENTS.template.md +2 -2
- package/build/agent/capabilities.md +54 -7
- package/build/agent/skills/adula-frontend-design/SKILL.md +1 -1
- package/build/agent/skills/idea-review/SKILL.md +26 -1
- package/build/agent/skills/module-review/SKILL.md +22 -0
- package/build/agent/skills/perf-review/SKILL.md +24 -0
- package/build/agent/skills/schema-review/SKILL.md +22 -0
- package/build/agent/skills/security-review/SKILL.md +24 -0
- package/build/agent/skills/ui-review/SKILL.md +22 -0
- package/build/commands/capabilities.d.ts +4 -0
- package/build/commands/capabilities.js +35 -4
- package/build/commands/doctor.js +37 -1
- package/build/commands/gaps.js +16 -6
- package/build/commands/install.js +19 -5
- package/build/commands/main.d.ts +4 -2
- package/build/commands/main.js +2 -0
- package/build/commands/module_add.js +2 -2
- package/build/commands/resource.js +1 -1
- package/build/commands/resource_snapshot.d.ts +15 -0
- package/build/commands/resource_snapshot.js +61 -0
- package/build/database/migrations/1770000000004_kit_collaboration.d.ts +5 -0
- package/build/database/migrations/1770000000004_kit_collaboration.js +10 -0
- package/build/database/migrations/1770000000005_kit_assignments.d.ts +5 -0
- package/build/database/migrations/1770000000005_kit_assignments.js +10 -0
- package/build/database/migrations/1770000000006_kit_messaging.d.ts +5 -0
- package/build/database/migrations/1770000000006_kit_messaging.js +10 -0
- package/build/database/migrations/1770000000007_kit_webhooks.d.ts +5 -0
- package/build/database/migrations/1770000000007_kit_webhooks.js +10 -0
- package/build/database/migrations/1770000000008_kit_imports.d.ts +5 -0
- package/build/database/migrations/1770000000008_kit_imports.js +10 -0
- package/build/database/migrations/1770000000010_kit_workflows.d.ts +5 -0
- package/build/database/migrations/1770000000010_kit_workflows.js +10 -0
- package/build/database/migrations/1770000000011_kit_managed_assignments.d.ts +5 -0
- package/build/database/migrations/1770000000011_kit_managed_assignments.js +10 -0
- package/build/database/migrations/1770000000012_kit_role_keys.d.ts +5 -0
- package/build/database/migrations/1770000000012_kit_role_keys.js +10 -0
- package/build/database/migrations/1770000000013_kit_notification_targets.d.ts +5 -0
- package/build/database/migrations/1770000000013_kit_notification_targets.js +10 -0
- package/build/database/migrations/1770000000014_kit_upload_grants.d.ts +5 -0
- package/build/database/migrations/1770000000014_kit_upload_grants.js +10 -0
- package/build/database/migrations/1770000000015_kit_inbound_webhooks.d.ts +5 -0
- package/build/database/migrations/1770000000015_kit_inbound_webhooks.js +10 -0
- package/build/index.d.ts +31 -2
- package/build/index.js +17 -2
- package/build/src/admin/contracts.d.ts +7 -0
- package/build/src/admin/contracts.js +34 -12
- package/build/src/admin/controller.d.ts +2 -0
- package/build/src/admin/controller.js +52 -1
- package/build/src/admin/presentation.d.ts +6 -0
- package/build/src/admin/record_title.d.ts +14 -0
- package/build/src/admin/record_title.js +50 -0
- package/build/src/admin/resource_service.d.ts +184 -2
- package/build/src/admin/resource_service.js +713 -48
- package/build/src/attachments/attachment_service.d.ts +12 -0
- package/build/src/attachments/attachment_service.js +28 -2
- package/build/src/attachments/upload_grants.d.ts +44 -0
- package/build/src/attachments/upload_grants.js +105 -0
- package/build/src/auth/ability.d.ts +1 -1
- package/build/src/auth/ability.js +4 -1
- package/build/src/auth/actor_store.js +6 -1
- package/build/src/auth/conditions.d.ts +15 -0
- package/build/src/auth/conditions.js +36 -0
- package/build/src/auth/sql.js +6 -2
- package/build/src/collaboration/assignments.d.ts +129 -0
- package/build/src/collaboration/assignments.js +333 -0
- package/build/src/collaboration/record_collaboration.d.ts +86 -0
- package/build/src/collaboration/record_collaboration.js +348 -0
- package/build/src/commands/agent_assets.js +5 -0
- package/build/src/commands/capabilities.d.ts +19 -0
- package/build/src/commands/capabilities.js +179 -0
- package/build/src/commands/doctor.d.ts +31 -0
- package/build/src/commands/doctor.js +114 -0
- package/build/src/commands/gap_report.d.ts +50 -2
- package/build/src/commands/gap_report.js +102 -4
- package/build/src/commands/generator.js +3 -3
- package/build/src/commands/snapshot.d.ts +28 -0
- package/build/src/commands/snapshot.js +48 -0
- package/build/src/commands/source_markers.d.ts +10 -1
- package/build/src/commands/source_markers.js +36 -4
- package/build/src/core/administration_guard.js +3 -1
- package/build/src/core/message_templates.d.ts +83 -0
- package/build/src/core/message_templates.js +293 -0
- package/build/src/core/module_seed.d.ts +15 -0
- package/build/src/core/module_seed.js +31 -0
- package/build/src/core/notifications.d.ts +18 -1
- package/build/src/core/notifications.js +27 -1
- package/build/src/core/roles.d.ts +27 -1
- package/build/src/core/roles.js +133 -5
- package/build/src/database/schema.d.ts +45 -0
- package/build/src/database/schema.js +290 -0
- package/build/src/eslint/index.js +26 -0
- package/build/src/events/outbox.d.ts +1 -0
- package/build/src/events/outbox.js +1 -1
- package/build/src/events/record_mutation.d.ts +11 -0
- package/build/src/events/record_mutation.js +15 -2
- package/build/src/integrations/imports.d.ts +74 -0
- package/build/src/integrations/imports.js +333 -0
- package/build/src/integrations/inbound_webhooks.d.ts +94 -0
- package/build/src/integrations/inbound_webhooks.js +276 -0
- package/build/src/integrations/openapi.d.ts +39 -0
- package/build/src/integrations/openapi.js +323 -0
- package/build/src/integrations/print.d.ts +37 -0
- package/build/src/integrations/print.js +124 -0
- package/build/src/integrations/webhooks.d.ts +98 -0
- package/build/src/integrations/webhooks.js +298 -0
- package/build/src/resource/define_resource.d.ts +1 -0
- package/build/src/resource/define_resource.js +21 -1
- package/build/src/resource/registry.d.ts +3 -0
- package/build/src/resource/registry.js +42 -0
- package/build/src/resource/types.d.ts +67 -1
- package/build/src/resource/values.js +2 -1
- package/build/src/services/settings.d.ts +13 -1
- package/build/src/services/settings.js +9 -2
- package/build/src/workflows/define_workflow.d.ts +124 -0
- package/build/src/workflows/define_workflow.js +123 -0
- package/build/src/workflows/engine.d.ts +141 -0
- package/build/src/workflows/engine.js +752 -0
- package/build/stubs/resource_contract.txt +103 -41
- package/package.json +7 -3
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const TITLE_TYPES = new Set(['string', 'text', 'integer', 'money', 'date', 'datetime', 'lookup']);
|
|
2
|
+
/**
|
|
3
|
+
* The fields that name a record wherever it is referenced (#47, #32): the resource's
|
|
4
|
+
* `title`, or else its first sequence field and its first text field in `list`. Lookup
|
|
5
|
+
* keys are never shown raw; declared lookup fields are shown by their Arabic label.
|
|
6
|
+
*/
|
|
7
|
+
export function titleFields(resource) {
|
|
8
|
+
if (resource.title)
|
|
9
|
+
return [...resource.title];
|
|
10
|
+
const sequence = Object.keys(resource.fields).find((key) => resource.fields[key].sequence);
|
|
11
|
+
const text = resource.list.find((key) => {
|
|
12
|
+
const field = resource.fields[key];
|
|
13
|
+
return (field.type === 'string' || field.type === 'text') && !field.sequence;
|
|
14
|
+
});
|
|
15
|
+
return [sequence, text].filter((key) => key !== undefined);
|
|
16
|
+
}
|
|
17
|
+
/** Definition check: title fields exist, are readable and have a displayable type. */
|
|
18
|
+
export function assertTitle(resource) {
|
|
19
|
+
if (!resource.title)
|
|
20
|
+
return;
|
|
21
|
+
if (!resource.title.length)
|
|
22
|
+
throw new Error(`${resource.name}: title needs at least one field`);
|
|
23
|
+
const readable = new Set(resource.serialize ?? [...resource.list, ...resource.show]);
|
|
24
|
+
for (const key of resource.title) {
|
|
25
|
+
const field = resource.fields[key];
|
|
26
|
+
if (!field)
|
|
27
|
+
throw new Error(`Unknown field: ${key}`);
|
|
28
|
+
if (!TITLE_TYPES.has(field.type))
|
|
29
|
+
throw new Error(`${resource.name}: title field ${key} cannot be a ${field.type}`);
|
|
30
|
+
if (!readable.has(key))
|
|
31
|
+
throw new Error(`${resource.name}: title field ${key} must be serialized`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The title of one serialized record, read after field-level filtering so it never shows
|
|
36
|
+
* a value the viewer may not read. Returns null when no title field has a value.
|
|
37
|
+
*/
|
|
38
|
+
export function formatTitle(resource, record, lookupLabel) {
|
|
39
|
+
const parts = [];
|
|
40
|
+
for (const key of titleFields(resource)) {
|
|
41
|
+
const value = record[key];
|
|
42
|
+
if (value === null || value === undefined || value === '')
|
|
43
|
+
continue;
|
|
44
|
+
const field = resource.fields[key];
|
|
45
|
+
parts.push(field.type === 'lookup'
|
|
46
|
+
? (lookupLabel(field.group, String(value)) ?? String(value))
|
|
47
|
+
: String(value));
|
|
48
|
+
}
|
|
49
|
+
return parts.length ? parts.join(' · ') : null;
|
|
50
|
+
}
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
2
|
import type { ResourceRegistry } from '../resource/registry.js';
|
|
3
|
-
import type { Action, RecordData, Resource, SerializedRecord } from '../resource/types.js';
|
|
3
|
+
import type { Action, JsonValue, RecordData, Resource, SerializedRecord } from '../resource/types.js';
|
|
4
4
|
import { type Actor, type KitAbility } from '../auth/ability.js';
|
|
5
|
+
import { type Conditions } from '../auth/conditions.js';
|
|
5
6
|
import type { ResourceDescription, ResourceNavigation, ResourceField } from './presentation.js';
|
|
7
|
+
export type AggregateOptions = {
|
|
8
|
+
/** Up to three queryable fields (docStatus and orgUnitId are also accepted). */
|
|
9
|
+
groupBy?: string[];
|
|
10
|
+
/** Count rows per group (default true). */
|
|
11
|
+
count?: boolean;
|
|
12
|
+
/** Integer or money fields to total per group; money totals are decimal strings. */
|
|
13
|
+
sum?: string[];
|
|
14
|
+
/** Equality filters, as in list(). */
|
|
15
|
+
filters?: Record<string, unknown>;
|
|
16
|
+
/** Role-rule style conditions ($eq, $ne, $in, $lt, $gt, $like, "$actor.id"). */
|
|
17
|
+
where?: Conditions;
|
|
18
|
+
search?: string;
|
|
19
|
+
};
|
|
20
|
+
export type AggregateRow = {
|
|
21
|
+
group: Record<string, JsonValue>;
|
|
22
|
+
count?: number;
|
|
23
|
+
sum?: Record<string, string | null>;
|
|
24
|
+
};
|
|
6
25
|
export type ListOptions = {
|
|
7
26
|
limit?: number;
|
|
8
27
|
cursor?: string;
|
|
@@ -10,6 +29,8 @@ export type ListOptions = {
|
|
|
10
29
|
sort?: string;
|
|
11
30
|
direction?: 'asc' | 'desc';
|
|
12
31
|
filters?: Record<string, unknown>;
|
|
32
|
+
/** Only records carrying this tag (see RecordCollaboration.setTags). */
|
|
33
|
+
tag?: string;
|
|
13
34
|
estimate?: boolean;
|
|
14
35
|
};
|
|
15
36
|
/**
|
|
@@ -17,10 +38,30 @@ export type ListOptions = {
|
|
|
17
38
|
* indirectly, so it needs unconditional view access at the field's level.
|
|
18
39
|
*/
|
|
19
40
|
export declare function canQueryField(resource: Resource, actor: Actor, ability: KitAbility, key: string): boolean;
|
|
41
|
+
/** Options of ResourceService.systemSave. */
|
|
42
|
+
export type SystemSaveOptions = {
|
|
43
|
+
/** The user recorded as the author: created/updated by, activity and events. */
|
|
44
|
+
actorId: number;
|
|
45
|
+
/** Write inside the module's transaction. */
|
|
46
|
+
trx?: Knex.Transaction;
|
|
47
|
+
/** Why module code wrote the record; stored with the activity entry. */
|
|
48
|
+
reason?: string;
|
|
49
|
+
/** Optimistic lock: when given, it must match the stored version. */
|
|
50
|
+
version?: number;
|
|
51
|
+
/**
|
|
52
|
+
* The person who chose the values, when module code writes a choice made by a user,
|
|
53
|
+
* such as a supervisor reassigning a record. A new value of a user field must then be
|
|
54
|
+
* eligible for them as in a user save; without it, any active member qualifies on
|
|
55
|
+
* unscoped resources.
|
|
56
|
+
*/
|
|
57
|
+
chooser?: Actor;
|
|
58
|
+
};
|
|
20
59
|
export declare class ResourceService {
|
|
21
60
|
private db;
|
|
22
61
|
private registry;
|
|
23
62
|
constructor(db: Knex, registry: ResourceRegistry);
|
|
63
|
+
/** The Arabic label of a registered resource, for notifications and titles. */
|
|
64
|
+
label(name: string): string;
|
|
24
65
|
/** Project navigation is derived from registered resources and the current actor. */
|
|
25
66
|
navigation(actor: Actor): ResourceNavigation;
|
|
26
67
|
describe(name: string, actor: Actor): ResourceDescription;
|
|
@@ -33,7 +74,20 @@ export declare class ResourceService {
|
|
|
33
74
|
private scopedQuery;
|
|
34
75
|
private columns;
|
|
35
76
|
private find;
|
|
77
|
+
/** A live record regardless of any actor's scope, for system writes. */
|
|
78
|
+
private findAny;
|
|
36
79
|
private requireRecord;
|
|
80
|
+
/**
|
|
81
|
+
* Authorizes one record for collaboration features (comments, tags, assignments...).
|
|
82
|
+
* Scope and conditional rules apply exactly as for show/update.
|
|
83
|
+
*/
|
|
84
|
+
access(name: string, id: number, actor: Actor, action?: Action, db?: Knex): Promise<{
|
|
85
|
+
resource: Resource;
|
|
86
|
+
record: RecordData;
|
|
87
|
+
ability: KitAbility;
|
|
88
|
+
}>;
|
|
89
|
+
/** Whether a (possibly other) actor may perform an action on a record; never throws for denial. */
|
|
90
|
+
permits(name: string, id: number, actor: Actor, action?: Action): Promise<boolean>;
|
|
37
91
|
list(name: string, actor: Actor, options?: ListOptions): Promise<{
|
|
38
92
|
data: SerializedRecord[];
|
|
39
93
|
permissions: {
|
|
@@ -47,7 +101,24 @@ export declare class ResourceService {
|
|
|
47
101
|
related: Record<string, SerializedRecord[]>;
|
|
48
102
|
}>;
|
|
49
103
|
private canQueryField;
|
|
104
|
+
/**
|
|
105
|
+
* Counts and totals over the records the actor may view, grouped by queryable fields,
|
|
106
|
+
* for dashboards. Authorization is list()'s: the same rules, organization scope and
|
|
107
|
+
* soft-delete filter apply, and every grouped, totalled or filtered field must be one
|
|
108
|
+
* the actor may query (E_FIELD_FORBIDDEN otherwise), so no hidden value leaks.
|
|
109
|
+
*/
|
|
110
|
+
aggregate(name: string, actor: Actor, options?: AggregateOptions): Promise<{
|
|
111
|
+
rows: AggregateRow[];
|
|
112
|
+
truncated: boolean;
|
|
113
|
+
}>;
|
|
50
114
|
private preload;
|
|
115
|
+
/** Formats record titles of one resource, loading the labels of its title lookups once. */
|
|
116
|
+
private titler;
|
|
117
|
+
/**
|
|
118
|
+
* Titles of records the actor may view, read under the actor's field access (#32).
|
|
119
|
+
* Records the actor cannot view are left out; callers fall back to the record id.
|
|
120
|
+
*/
|
|
121
|
+
titles(name: string, ids: readonly number[], actor: Actor): Promise<Map<number, string>>;
|
|
51
122
|
show(name: string, id: number, actor: Actor): Promise<{
|
|
52
123
|
data: SerializedRecord;
|
|
53
124
|
permissions: Partial<Record<Action, boolean>>;
|
|
@@ -57,6 +128,10 @@ export declare class ResourceService {
|
|
|
57
128
|
id?: number;
|
|
58
129
|
search?: string;
|
|
59
130
|
cursor?: string;
|
|
131
|
+
/** User fields: the organization unit chosen in the form. */
|
|
132
|
+
orgUnitId?: number;
|
|
133
|
+
/** User fields: choices for a list filter instead of a form. */
|
|
134
|
+
purpose?: 'form' | 'filter';
|
|
60
135
|
}): Promise<{
|
|
61
136
|
data: {
|
|
62
137
|
value: string;
|
|
@@ -64,11 +139,25 @@ export declare class ResourceService {
|
|
|
64
139
|
}[];
|
|
65
140
|
nextCursor: string | null;
|
|
66
141
|
}>;
|
|
142
|
+
/**
|
|
143
|
+
* Choices for a user field. A form lists active members of the record's unit or its
|
|
144
|
+
* ancestors (the users the record is visible to through membership); a filter lists
|
|
145
|
+
* active users who share organization scope with the actor. Only names are returned.
|
|
146
|
+
*/
|
|
147
|
+
private userOptions;
|
|
148
|
+
/**
|
|
149
|
+
* Active users eligible for a user field: members of the unit at `path` or of one of
|
|
150
|
+
* its ancestors, or (without a path) users sharing organization scope with the actor.
|
|
151
|
+
* A system write on an unscoped resource passes no actor: any active member qualifies.
|
|
152
|
+
*/
|
|
153
|
+
private eligibleUsers;
|
|
67
154
|
/** Deferred relation reads re-authorize the parent and each child on every request. */
|
|
68
155
|
children(name: string, id: number, actor: Actor): Promise<Record<string, {
|
|
69
156
|
rows: SerializedRecord[];
|
|
70
157
|
hasMore: boolean;
|
|
71
158
|
}>>;
|
|
159
|
+
/** Inline children of an already authorized parent record. */
|
|
160
|
+
private childrenOf;
|
|
72
161
|
/** Active lookup labels for the lookup fields the actor may read on this resource. */
|
|
73
162
|
lookups(name: string, actor: Actor): Promise<Record<string, {
|
|
74
163
|
value: string;
|
|
@@ -88,10 +177,66 @@ export declare class ResourceService {
|
|
|
88
177
|
actorEmail: string | null;
|
|
89
178
|
createdAt: string;
|
|
90
179
|
}[]>;
|
|
91
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Inline children and recent activity of one record, authorized with a single record
|
|
182
|
+
* read (for deferred page props that would otherwise read the record twice).
|
|
183
|
+
*/
|
|
184
|
+
details(name: string, id: number, actor: Actor): Promise<{
|
|
185
|
+
children: Record<string, {
|
|
186
|
+
rows: SerializedRecord[];
|
|
187
|
+
hasMore: boolean;
|
|
188
|
+
}>;
|
|
189
|
+
activity: {
|
|
190
|
+
id: number;
|
|
191
|
+
action: Action;
|
|
192
|
+
fields: string[];
|
|
193
|
+
actorId: number;
|
|
194
|
+
actorName: string | null;
|
|
195
|
+
/**
|
|
196
|
+
* @deprecated Always null. Kept so project-owned copies of resource-show from
|
|
197
|
+
* earlier releases still compile; they fall back to the actor id.
|
|
198
|
+
*/
|
|
199
|
+
actorEmail: string | null;
|
|
200
|
+
createdAt: string;
|
|
201
|
+
}[];
|
|
202
|
+
}>;
|
|
203
|
+
/** show(), children() and activity() of one record from a single record read. */
|
|
204
|
+
record(name: string, id: number, actor: Actor): Promise<{
|
|
205
|
+
data: SerializedRecord;
|
|
206
|
+
permissions: Partial<Record<Action, boolean>>;
|
|
207
|
+
related: Record<string, SerializedRecord[]>;
|
|
208
|
+
children: Record<string, {
|
|
209
|
+
rows: SerializedRecord[];
|
|
210
|
+
hasMore: boolean;
|
|
211
|
+
}>;
|
|
212
|
+
activity: {
|
|
213
|
+
id: number;
|
|
214
|
+
action: Action;
|
|
215
|
+
fields: string[];
|
|
216
|
+
actorId: number;
|
|
217
|
+
actorName: string | null;
|
|
218
|
+
/**
|
|
219
|
+
* @deprecated Always null. Kept so project-owned copies of resource-show from
|
|
220
|
+
* earlier releases still compile; they fall back to the actor id.
|
|
221
|
+
*/
|
|
222
|
+
actorEmail: string | null;
|
|
223
|
+
createdAt: string;
|
|
224
|
+
}[];
|
|
225
|
+
}>;
|
|
226
|
+
private activityOf;
|
|
227
|
+
/**
|
|
228
|
+
* The form description for create (no id) or update. `defaults` pre-fills a create form
|
|
229
|
+
* (#48), for example `?defaults[violation]=13`: only visible form fields are used, a
|
|
230
|
+
* related record must be viewable by the actor and a lookup must be active. Anything else
|
|
231
|
+
* is dropped. Defaults are only initial values; saving validates as usual.
|
|
232
|
+
*/
|
|
233
|
+
editor(name: string, actor: Actor, id?: number, request?: {
|
|
234
|
+
defaults?: Record<string, unknown>;
|
|
235
|
+
}): Promise<{
|
|
92
236
|
mode: string;
|
|
93
237
|
name: string;
|
|
94
238
|
label: string;
|
|
239
|
+
recordLabel: string | null;
|
|
95
240
|
fields: ({
|
|
96
241
|
label: import("../resource/types.js").Label;
|
|
97
242
|
column?: string;
|
|
@@ -131,6 +276,18 @@ export declare class ResourceService {
|
|
|
131
276
|
type: "belongsTo";
|
|
132
277
|
resource: string;
|
|
133
278
|
key: string;
|
|
279
|
+
} | {
|
|
280
|
+
label: import("../resource/types.js").Label;
|
|
281
|
+
column?: string;
|
|
282
|
+
required?: boolean;
|
|
283
|
+
unique?: boolean;
|
|
284
|
+
sortable?: boolean;
|
|
285
|
+
searchable?: boolean;
|
|
286
|
+
filterable?: boolean;
|
|
287
|
+
permissionLevel?: number;
|
|
288
|
+
sequence?: string;
|
|
289
|
+
type: "user";
|
|
290
|
+
key: string;
|
|
134
291
|
} | {
|
|
135
292
|
label: import("../resource/types.js").Label;
|
|
136
293
|
column?: string;
|
|
@@ -160,6 +317,8 @@ export declare class ResourceService {
|
|
|
160
317
|
group: string;
|
|
161
318
|
key: string;
|
|
162
319
|
})[];
|
|
320
|
+
/** Initial values of a create form, already checked against the actor's access. */
|
|
321
|
+
defaults: SerializedRecord;
|
|
163
322
|
inline: Record<string, {
|
|
164
323
|
rows: SerializedRecord[];
|
|
165
324
|
hasMore: boolean;
|
|
@@ -182,13 +341,36 @@ export declare class ResourceService {
|
|
|
182
341
|
label: string;
|
|
183
342
|
}[];
|
|
184
343
|
scoped: boolean;
|
|
344
|
+
/** The belongsTo field whose record decides the unit; the form shows no unit picker. */
|
|
345
|
+
scopeFrom: string | null;
|
|
185
346
|
record: SerializedRecord | null;
|
|
186
347
|
}>;
|
|
187
348
|
save(name: string, actor: Actor, input: RecordData, id?: number, transaction?: Knex.Transaction): Promise<SerializedRecord>;
|
|
349
|
+
/**
|
|
350
|
+
* A write decided by module code rather than by a user's role rules: state transitions,
|
|
351
|
+
* snapshots and listener updates. It runs the validator, hooks, lookup, relation and
|
|
352
|
+
* attachment checks, versioning and the audit trail exactly like save(), and skips only
|
|
353
|
+
* the actor's role rules and organization scope. Values may set any stored field except
|
|
354
|
+
* sequences and inline children. Updates merge the given values into the stored record.
|
|
355
|
+
* Returns the full stored record; module code must not send it to users unfiltered.
|
|
356
|
+
*/
|
|
357
|
+
systemSave(name: string, values: RecordData, id: number | undefined, options: SystemSaveOptions): Promise<RecordData>;
|
|
358
|
+
/**
|
|
359
|
+
* Moves the records whose scope follows this parent (`scope: { from }`) to the parent's
|
|
360
|
+
* current organization unit, through systemSave. Call it from a listener on the parent's
|
|
361
|
+
* `updated` event, or right after moving the parent. Returns the number of moved records.
|
|
362
|
+
*/
|
|
363
|
+
rehome(parentName: string, parentId: number, options: Omit<SystemSaveOptions, 'version'>): Promise<number>;
|
|
188
364
|
private persist;
|
|
189
365
|
private requireVersion;
|
|
190
366
|
/** Inline children share the parent's draft state, organization and update authority. */
|
|
191
367
|
private requireInlineParents;
|
|
192
368
|
transition(name: string, id: number, actor: Actor, action: 'delete' | 'submit' | 'cancel', version?: unknown, transaction?: Knex.Transaction): Promise<SerializedRecord>;
|
|
369
|
+
/**
|
|
370
|
+
* Amend-by-copy: a cancelled document is copied into a new draft that points to
|
|
371
|
+
* it through amended_from_id, together with its inline lines. The original stays
|
|
372
|
+
* cancelled and unchanged; sequence fields receive new numbers.
|
|
373
|
+
*/
|
|
374
|
+
amend(name: string, id: number, actor: Actor, transaction?: Knex.Transaction): Promise<SerializedRecord>;
|
|
193
375
|
private audit;
|
|
194
376
|
}
|