@dforge-core/metadata 0.0.26 → 0.0.29
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/CHANGELOG.md +21 -0
- package/dist/index.d.ts +170 -8
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/card_layouts.schema.json +141 -0
- package/schemas/data_views.schema.json +2 -14
- package/schemas/entity.schema.json +54 -2
- package/schemas/manifest.schema.json +4 -0
- package/schemas/reports.schema.json +2 -2
- package/schemas/stored_procedures.schema.json +125 -0
- package/src/card-layouts.ts +103 -0
- package/src/data-views.ts +2 -4
- package/src/entity.ts +4 -2
- package/src/index.ts +23 -3
- package/src/manifest.ts +2 -0
- package/src/reports.ts +6 -2
- package/src/stored-procedures.ts +75 -0
|
@@ -38,6 +38,10 @@
|
|
|
38
38
|
"toString": {
|
|
39
39
|
"description": "Display pattern using column placeholders, e.g. \"{first_name} {last_name}\". Optional in extension entities (with `extends`). No `type` constraint here because `toString` collides with Object.prototype.toString in JSON validators — they read the inherited function and reject it, even when the property is absent from the JSON."
|
|
40
40
|
},
|
|
41
|
+
"comments": {
|
|
42
|
+
"type": "boolean",
|
|
43
|
+
"description": "Records of this entity accept comments \u2014 the composer and thread appear on the record card, beside the audit history. Opt-in per entity; `comments` in the manifest sets a module-wide default that this overrides in both directions."
|
|
44
|
+
},
|
|
41
45
|
"traits": {
|
|
42
46
|
"type": "array",
|
|
43
47
|
"description": "Entity traits expanded during module install (authoring shortcut). Trait definitions loaded from DB (seeded by metadata module).",
|
|
@@ -221,9 +225,48 @@
|
|
|
221
225
|
},
|
|
222
226
|
"additionalProperties": false
|
|
223
227
|
},
|
|
228
|
+
"registryColumnParams": {
|
|
229
|
+
"type": "object",
|
|
230
|
+
"description": "params of an accumulation (A) or ledger (L) registry column. The lock lists are what BOTH generated guards freeze — the posted-document guard while the document is posted, the period guard while its period is closed — and they are required: install refuses a registry column that omits or empties them. The header's periodDateField and the state column are watched in addition, whatever the list says.",
|
|
231
|
+
"required": ["lockedFields"],
|
|
232
|
+
"properties": {
|
|
233
|
+
"lockedFields": {
|
|
234
|
+
"type": "array",
|
|
235
|
+
"minItems": 1,
|
|
236
|
+
"items": { "type": "string", "minLength": 1 },
|
|
237
|
+
"description": "Header fields frozen while the document is posted and while its period is closed. Required. [\"*\"] freezes the whole row."
|
|
238
|
+
},
|
|
239
|
+
"lockedLineFields": {
|
|
240
|
+
"type": "array",
|
|
241
|
+
"minItems": 1,
|
|
242
|
+
"items": { "type": "string", "minLength": 1 },
|
|
243
|
+
"description": "Line fields frozen under a posted or period-closed header. Required when lineEntity is declared, rejected when it is not. [\"*\"] freezes the whole row; the line's foreign key to the header is watched in addition."
|
|
244
|
+
},
|
|
245
|
+
"lineEntity": { "type": "string", "description": "The line entity, defined in this module. Declare together with lineField and lockedLineFields, or none of the three for a document without lines." },
|
|
246
|
+
"lineField": { "type": "string", "description": "The line's foreign-key column(s) to the header, comma-separated in the header's key order for a composite key." },
|
|
247
|
+
"stateField": { "type": "string", "description": "The bool column that records the posted state, when it is not the registry column itself. Written only by the register engine." },
|
|
248
|
+
"periodEntity": { "type": "string", "description": "Period entity this registry closes against — one of this module's, or 'module.entity' from a dependency." },
|
|
249
|
+
"periodDateField": { "type": "string", "description": "Header date column that resolves the period." },
|
|
250
|
+
"periodKeyField": { "type": "string", "default": "period_key" },
|
|
251
|
+
"periodClosedField": { "type": "string", "default": "closed" }
|
|
252
|
+
},
|
|
253
|
+
"dependencies": {
|
|
254
|
+
"lineEntity": ["lineField", "lockedLineFields"],
|
|
255
|
+
"lineField": ["lineEntity"],
|
|
256
|
+
"lockedLineFields": ["lineEntity"],
|
|
257
|
+
"periodEntity": ["periodDateField"]
|
|
258
|
+
},
|
|
259
|
+
"additionalProperties": true
|
|
260
|
+
},
|
|
224
261
|
"field": {
|
|
225
262
|
"type": "object",
|
|
226
263
|
"description": "Entity column/field definition",
|
|
264
|
+
"allOf": [
|
|
265
|
+
{
|
|
266
|
+
"if": { "required": ["columnType"], "properties": { "columnType": { "enum": ["A", "L"] } } },
|
|
267
|
+
"then": { "required": ["params"], "properties": { "params": { "$ref": "#/$defs/registryColumnParams" } } }
|
|
268
|
+
}
|
|
269
|
+
],
|
|
227
270
|
"properties": {
|
|
228
271
|
"dbDatatype": {
|
|
229
272
|
"type": "string",
|
|
@@ -320,6 +363,15 @@
|
|
|
320
363
|
},
|
|
321
364
|
"serverDefault": {
|
|
322
365
|
"$ref": "#/$defs/serverDefault"
|
|
366
|
+
},
|
|
367
|
+
"pattern": {
|
|
368
|
+
"type": "string",
|
|
369
|
+
"description": "Format rule for this column, as an ECMAScript regex source. Overrides the field type's own pattern (field_type.def_params.pattern, which is what makes email/phone/url reject a malformed value). Enforced in the browser and again on data.insert / data.update, so keep to constructs both engines read alike: [0-9] and \\d are the same there, \\s is normalized to JavaScript's set, and a pattern that will not compile is skipped by both rather than enforced by one."
|
|
370
|
+
},
|
|
371
|
+
"patternFlags": {
|
|
372
|
+
"type": "string",
|
|
373
|
+
"description": "Flags for 'pattern', as a JavaScript regex literal would carry them; 'i' and 'm' are the two honoured, each at most once — the RegExp constructor rejects a repeated flag, and a rule the browser cannot compile is skipped there and would then be enforced by the API alone. JavaScript has no inline (?i), so case-insensitivity has to be stated here.",
|
|
374
|
+
"pattern": "^(i|m|im|mi)?$"
|
|
323
375
|
}
|
|
324
376
|
}
|
|
325
377
|
},
|
|
@@ -526,7 +578,7 @@
|
|
|
526
578
|
"accumulationConfig": {
|
|
527
579
|
"type": "object",
|
|
528
580
|
"description": "Configuration for simple accumulation (document without lines, e.g. receipt → stock).",
|
|
529
|
-
"required": ["balanceEntity", "dimensions", "resources"],
|
|
581
|
+
"required": ["balanceEntity", "dimensions", "resources", "lockedFields"],
|
|
530
582
|
"properties": {
|
|
531
583
|
"balanceEntity": { "type": "string", "description": "Balance entity code (e.g. 'stock')" },
|
|
532
584
|
"dimensions": {
|
|
@@ -551,7 +603,7 @@
|
|
|
551
603
|
"sign": { "$ref": "#/$defs/signConfig", "description": "Dynamic sign based on a field value (alternative to direction)" },
|
|
552
604
|
"autoCreateBalance": { "type": "boolean", "default": true },
|
|
553
605
|
"allowNegative": { "type": "boolean", "default": true },
|
|
554
|
-
"lockedFields": { "type": "array", "items": { "type": "string" }, "description": "Document fields locked when posted" }
|
|
606
|
+
"lockedFields": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "Document fields locked when posted. Required; [\"*\"] freezes the whole row." }
|
|
555
607
|
},
|
|
556
608
|
"additionalProperties": false
|
|
557
609
|
},
|
|
@@ -107,6 +107,10 @@
|
|
|
107
107
|
"enum": ["none", "minimal", "full"],
|
|
108
108
|
"description": "Default audit history mode for entities in this module ('full' captures every field change; 'minimal' captures only inserts/deletes; 'none' disables). Individual entities can override."
|
|
109
109
|
},
|
|
110
|
+
"comments": {
|
|
111
|
+
"type": "boolean",
|
|
112
|
+
"description": "Default for `comments` on every entity in this module. Individual entities override it, including overriding true with false."
|
|
113
|
+
},
|
|
110
114
|
"entities": {
|
|
111
115
|
"type": "object",
|
|
112
116
|
"description": "Entity definitions and extensions: entity code → relative path to entity JSON file. Dotted keys (e.g. 'fin.invoice') indicate extensions of other modules' entities (the entity file must have an 'extends' property).",
|
|
@@ -249,9 +249,9 @@
|
|
|
249
249
|
"$ref": "#/$defs/query",
|
|
250
250
|
"description": "Used when datasetType is 'Q'"
|
|
251
251
|
},
|
|
252
|
-
"
|
|
252
|
+
"spCd": {
|
|
253
253
|
"type": "string",
|
|
254
|
-
"description": "Used when datasetType is 'S'"
|
|
254
|
+
"description": "Used when datasetType is 'S': the stored-procedure code, as `logic/stored_procedures.json` keys it — NOT the PostgreSQL function name and never schema-qualified. `module.spCd` binds a dependency's procedure. Resolved to `report_ds.sp_id` at install. A role granting `report:<code>` must also grant `sp:<spCd>`, which no admin UI can add afterwards."
|
|
255
255
|
},
|
|
256
256
|
"columnsDef": {
|
|
257
257
|
"type": "object",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "dForge Module Stored Procedures",
|
|
4
|
+
"description": "Stored-procedure declarations for a dForge module package (logic/stored_procedures.json). Each entry registers one PostgreSQL function as a procedure a report dataset can bind with `datasetType: \"S\"` and `spCd`. The SQL that creates the function ships separately, as a CREATE OR REPLACE FUNCTION script under logic/reports/; this file does not name the script, it names the function the script creates. See docs/business-logic/stored-procedures.md.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": ["functionName"],
|
|
9
|
+
"description": "Keyed by stored-procedure code (sp_cd) — module-internal, referenced from a dataset's `spCd` and a role's `sp:` right. It may not contain a dot: a dot is the module qualifier in both of those key spaces.",
|
|
10
|
+
"properties": {
|
|
11
|
+
"description": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Label for the procedure, shown in the report editor's procedure picker. Defaults to the code."
|
|
14
|
+
},
|
|
15
|
+
"schemaName": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"pattern": "^[a-zA-Z_][a-zA-Z0-9_\\-]*$",
|
|
18
|
+
"description": "PostgreSQL schema holding the function. Defaults to the module's own schema, which is what a module-shipped function normally uses."
|
|
19
|
+
},
|
|
20
|
+
"functionName": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"pattern": "^[a-zA-Z_][a-zA-Z0-9_\\-]*$",
|
|
23
|
+
"description": "The PostgreSQL function's own name, unqualified — `report.run` calls SELECT * FROM \"schemaName\".\"functionName\"(...). Required: it is the one fact this file exists to record, and install fails naming it when absent."
|
|
24
|
+
},
|
|
25
|
+
"returnsTable": {
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"default": true,
|
|
28
|
+
"description": "The function is set-returning (RETURNS TABLE / SETOF). The only shape report.run projects."
|
|
29
|
+
},
|
|
30
|
+
"params": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"description": "The call signature, in order: report.run passes exactly one positional argument per entry and NOTHING else — no folder, no user. A function taking p_folder_uid / p_user_id can never be called, and install rejects the arity mismatch. Omit the block for a function taking no arguments.",
|
|
33
|
+
"items": { "$ref": "#/$defs/param" }
|
|
34
|
+
},
|
|
35
|
+
"columns": {
|
|
36
|
+
"type": "array",
|
|
37
|
+
"description": "Result columns, stored in dForge.sp_column and used to project the dataset. Omit the block and the registrar derives them from the function's own RETURNS TABLE / OUT column names. Declare it to set labels, widths, a currency/percent control or a refEntityCd link — a declared list is used as written and never merged with the signature. A function returning an unnamed SETOF composite or a bare scalar declares no column names, so it must list them here.",
|
|
38
|
+
"items": { "$ref": "#/$defs/column" }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"additionalProperties": false
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
"$defs": {
|
|
45
|
+
"param": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"required": ["paramCd"],
|
|
48
|
+
"properties": {
|
|
49
|
+
"paramCd": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"maxLength": 50,
|
|
52
|
+
"description": "Parameter code. Conventionally the function's own argument name (p_customer_id), though the call is positional."
|
|
53
|
+
},
|
|
54
|
+
"pgType": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"default": "bigint",
|
|
57
|
+
"description": "PostgreSQL type of the argument — this is what binds the value, and it is carried even when the value is null so an omitted optional argument arrives as a TYPED null. Defaults to `bigint`, so declare it for every argument that is not one. One of: bigint, integer, smallint, numeric, real, double precision, text, boolean, uuid, date, timestamp, timestamptz, time — or any alias PostgreSQL treats as the same type (int8, int4, int, int2, decimal, float8, float4, varchar, character varying, char, bpchar, bool, timestamp without time zone, timestamp with time zone, time without time zone). Case does not matter and a type modifier is ignored, so `numeric(18,2)` may be pasted straight from the signature. jsonb, arrays, enums and citext cannot be bound and are rejected at install. Enforced by SpParamTypes, which is where this list lives — left out of an enum here so the spellings install accepts are not flagged by an editor.",
|
|
58
|
+
"examples": ["bigint", "text", "date", "numeric(18,2)", "timestamptz", "uuid", "boolean"]
|
|
59
|
+
},
|
|
60
|
+
"fieldTypeCd": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"description": "Control the report editor copies into the report param when the procedure is bound there. Optional — derived from pgType when omitted."
|
|
63
|
+
},
|
|
64
|
+
"label": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"description": "Parameter label for that same copy."
|
|
67
|
+
},
|
|
68
|
+
"required": {
|
|
69
|
+
"type": "boolean",
|
|
70
|
+
"default": true,
|
|
71
|
+
"description": "Whether the parameter must have a value. Give every optional one DEFAULT NULL in the function signature."
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"additionalProperties": false
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
"column": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"required": ["columnCd"],
|
|
80
|
+
"properties": {
|
|
81
|
+
"columnCd": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"maxLength": 100,
|
|
84
|
+
"description": "Result column name as the function returns it. Unique within the procedure."
|
|
85
|
+
},
|
|
86
|
+
"label": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"description": "Column header. Defaults to the code."
|
|
89
|
+
},
|
|
90
|
+
"fieldTypeCd": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"default": "text",
|
|
93
|
+
"description": "Control that renders the value (number, currency, date, dropdown, flags, ...)."
|
|
94
|
+
},
|
|
95
|
+
"baseDatatypeCd": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"default": "string",
|
|
98
|
+
"description": "Underlying datatype the value is read as."
|
|
99
|
+
},
|
|
100
|
+
"orderNum": {
|
|
101
|
+
"type": "integer",
|
|
102
|
+
"description": "Display order. Defaults to declaration order in steps of 10."
|
|
103
|
+
},
|
|
104
|
+
"refEntityCd": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"description": "Entity this column links to, making the value clickable. Resolved within this module and its dependencies."
|
|
107
|
+
},
|
|
108
|
+
"refColumnCd": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "Column in the result holding the FK value for that link, when it is not this column."
|
|
111
|
+
},
|
|
112
|
+
"width": {
|
|
113
|
+
"type": "integer",
|
|
114
|
+
"description": "Column width in pixels."
|
|
115
|
+
},
|
|
116
|
+
"params": {
|
|
117
|
+
"type": "object",
|
|
118
|
+
"description": "Control parameters, the same shape an entity column's `params` takes — `options` for a dropdown or flags, `currency`, `align`, and so on.",
|
|
119
|
+
"additionalProperties": true
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"additionalProperties": false
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Card layouts — authoring shape of `ui/card_layouts.json`.
|
|
2
|
+
// Mirror of card_layouts.schema.json, and of the runtime CardLayout in
|
|
3
|
+
// @dforge/data's layouts.ts — the installer stores the body verbatim, so the
|
|
4
|
+
// two must not drift.
|
|
5
|
+
|
|
6
|
+
/** A field in a card section — either a bare column code or pixel sizing with it. */
|
|
7
|
+
export type CardFieldEntry = string | CardFieldDef;
|
|
8
|
+
|
|
9
|
+
export interface CardFieldDef {
|
|
10
|
+
column_cd: string;
|
|
11
|
+
/** Field width in px. */
|
|
12
|
+
width?: number;
|
|
13
|
+
/** Field height in px — for multiline/textarea fields. */
|
|
14
|
+
height?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** A group of fields laid out in 1, 2 or 3 columns. */
|
|
18
|
+
export interface ColumnGroupSection {
|
|
19
|
+
type: "columnGroup";
|
|
20
|
+
code: string;
|
|
21
|
+
/** Section heading, in the module's authoring language. The installer gives it an
|
|
22
|
+
* `entity_column_group` row keyed on this section's `code`, so
|
|
23
|
+
* `translations/<locale>.json` localizes it under
|
|
24
|
+
* `entities.<entity>.columnGroups.<code>.label` and the card renders that instead. */
|
|
25
|
+
label?: string;
|
|
26
|
+
columns: CardFieldEntry[];
|
|
27
|
+
/** Field columns across the group (1-3). Defaults to the card's own setting. */
|
|
28
|
+
cols?: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* An embedded detail grid for a 1:N set column — the master/detail building
|
|
33
|
+
* block. The label comes from the set column's own metadata.
|
|
34
|
+
*/
|
|
35
|
+
export interface SetSection {
|
|
36
|
+
type: "set";
|
|
37
|
+
code: string;
|
|
38
|
+
/** Set column code on this entity (columnType 'S'). */
|
|
39
|
+
setField: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Reference to a tab item: a columnGroup section's code, or a set column's code. */
|
|
43
|
+
export interface CardTabRef {
|
|
44
|
+
type: "section" | "set";
|
|
45
|
+
code: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** A tab bar whose tabs are other sections — several detail grids without one long form. */
|
|
49
|
+
export interface TabGroupSection {
|
|
50
|
+
type: "tabGroup";
|
|
51
|
+
code: string;
|
|
52
|
+
tabs: CardTabRef[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type CardSection = ColumnGroupSection | SetSection | TabGroupSection;
|
|
56
|
+
|
|
57
|
+
/** Per-set-field renderer choice, keyed by the set column code. */
|
|
58
|
+
export interface CardSetConfig {
|
|
59
|
+
viewType?: "grid" | "list";
|
|
60
|
+
/** Opaque per-renderer options, passed verbatim to the set registration. */
|
|
61
|
+
options?: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The layout body, stored verbatim into `dForge.entity_view_layout.layout`. */
|
|
65
|
+
export interface CardLayout {
|
|
66
|
+
sections: CardSection[];
|
|
67
|
+
sets?: Record<string, CardSetConfig>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* A module-shipped card layout (value in the card_layouts map; the key is the
|
|
72
|
+
* layout name).
|
|
73
|
+
*
|
|
74
|
+
* Rows written from here carry `module_id`, so the installer recreates them on
|
|
75
|
+
* every install and removes them on uninstall. A layout the tenant drew in the
|
|
76
|
+
* card editor has `module_id` NULL and is never touched.
|
|
77
|
+
*/
|
|
78
|
+
export interface CardLayoutDef {
|
|
79
|
+
/**
|
|
80
|
+
* Entity code the layout belongs to. Unqualified means this module owns the
|
|
81
|
+
* entity; `module.entity` targets another module's (the bridge case).
|
|
82
|
+
*/
|
|
83
|
+
entity: string;
|
|
84
|
+
/**
|
|
85
|
+
* Entity view the layout hangs off. Defaults to `"default"` — the same
|
|
86
|
+
* fallback the runtime uses for an entity with no folder binding of its own.
|
|
87
|
+
* Matched against the entity's declared views case-insensitively, and filed
|
|
88
|
+
* under their spelling.
|
|
89
|
+
*/
|
|
90
|
+
view?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Whether this layout opens by default. Honoured on FIRST install only, and
|
|
93
|
+
* only when the view has no default yet: once a tenant has chosen their own,
|
|
94
|
+
* an upgrade does not take it back.
|
|
95
|
+
*/
|
|
96
|
+
isDefault?: boolean;
|
|
97
|
+
/** Human-readable note for the package author. Not stored. */
|
|
98
|
+
description?: string;
|
|
99
|
+
layout: CardLayout;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** `ui/card_layouts.json` — layout name → definition. */
|
|
103
|
+
export type CardLayoutsFile = Record<string, CardLayoutDef>;
|
package/src/data-views.ts
CHANGED
|
@@ -17,7 +17,6 @@ export type ViewType =
|
|
|
17
17
|
| "gallery"
|
|
18
18
|
| "tree-grid"
|
|
19
19
|
| "diagram"
|
|
20
|
-
| "master-detail"
|
|
21
20
|
| "library"
|
|
22
21
|
| "matrix";
|
|
23
22
|
|
|
@@ -30,7 +29,6 @@ export const dataViewKinds: readonly NamedKind[] = [
|
|
|
30
29
|
{ cd: "gallery", name: "Gallery" },
|
|
31
30
|
{ cd: "tree-grid", name: "Tree Grid" },
|
|
32
31
|
{ cd: "diagram", name: "Diagram" },
|
|
33
|
-
{ cd: "master-detail", name: "Master / Detail" },
|
|
34
32
|
{ cd: "library", name: "Library" },
|
|
35
33
|
{ cd: "matrix", name: "Matrix" },
|
|
36
34
|
] as const;
|
|
@@ -55,7 +53,7 @@ export interface DataSource {
|
|
|
55
53
|
entityCode: string;
|
|
56
54
|
/** Nesting level (0 = root, 1+ = detail). */
|
|
57
55
|
level?: number;
|
|
58
|
-
/** Human-readable label
|
|
56
|
+
/** Human-readable label for this data source. */
|
|
59
57
|
label?: string;
|
|
60
58
|
/** Column configuration. */
|
|
61
59
|
columns?: ViewColumn[];
|
|
@@ -121,7 +119,7 @@ export interface DataViewDef {
|
|
|
121
119
|
/** Bootstrap icon class (e.g. 'bi-bounding-box'). */
|
|
122
120
|
icon?: string;
|
|
123
121
|
description?: string;
|
|
124
|
-
/** Data sources (at least one
|
|
122
|
+
/** Data sources (at least one). Only the first is rendered today. */
|
|
125
123
|
dataSources: DataSource[];
|
|
126
124
|
/** Default filter applied to all sources unless one declares its own. */
|
|
127
125
|
filter?: Filter;
|
package/src/entity.ts
CHANGED
|
@@ -130,8 +130,8 @@ export interface AccumulationConfig {
|
|
|
130
130
|
sign?: SignConfig;
|
|
131
131
|
autoCreateBalance?: boolean;
|
|
132
132
|
allowNegative?: boolean;
|
|
133
|
-
/** Document fields locked once posted. */
|
|
134
|
-
lockedFields
|
|
133
|
+
/** Document fields locked once posted. Required; `["*"]` freezes the whole row. */
|
|
134
|
+
lockedFields: string[];
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/** One registry target within an L-column's `registries` array. */
|
|
@@ -167,6 +167,8 @@ export interface EntityDef {
|
|
|
167
167
|
viewSql?: string;
|
|
168
168
|
/** Display pattern using column placeholders, e.g. "{first_name} {last_name}". */
|
|
169
169
|
toString?: string;
|
|
170
|
+
/** Records of this entity accept comments (composer + thread on the card). */
|
|
171
|
+
comments?: boolean;
|
|
170
172
|
/** Traits expanded at install time. */
|
|
171
173
|
traits?: TraitCd[];
|
|
172
174
|
/** Column definitions keyed by column code. Optional when a trait (e.g. `period`) supplies all columns. */
|
package/src/index.ts
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// kinds, report viz/chart types, plus helpers that derive physical metadata
|
|
6
6
|
// from a friendly field-type choice;
|
|
7
7
|
// • structural types — the authoring shape of every module-package file
|
|
8
|
-
// (manifest, entities, data views, reports,
|
|
9
|
-
// jobs, triggers, webhooks, print templates, seed data,
|
|
10
|
-
// from the JSON schemas under docs/schemas/.
|
|
8
|
+
// (manifest, entities, data views, reports, stored procedures, menus, folders,
|
|
9
|
+
// roles, settings, jobs, triggers, webhooks, print templates, seed data,
|
|
10
|
+
// actions), mirrored from the JSON schemas under docs/schemas/.
|
|
11
11
|
//
|
|
12
12
|
// No runtime dependencies; safe to import from editors, the web app, the CLI,
|
|
13
13
|
// the MCP server and the VS Code extension.
|
|
@@ -105,6 +105,13 @@ export {
|
|
|
105
105
|
type VizType,
|
|
106
106
|
} from "./reports";
|
|
107
107
|
|
|
108
|
+
export type {
|
|
109
|
+
StoredProceduresFile,
|
|
110
|
+
StoredProcedureDef,
|
|
111
|
+
SpParamDef,
|
|
112
|
+
SpColumnDef,
|
|
113
|
+
} from "./stored-procedures";
|
|
114
|
+
|
|
108
115
|
export type { ManifestDef, ManifestAuthor, ModuleDependency, ModuleFeature } from "./manifest";
|
|
109
116
|
export type { DepsFile, DepEntity, DepColumn, DepColumnType, DepColumnMode, DepProvenance, DepProvenanceKind } from "./deps";
|
|
110
117
|
export { DEP_COLUMN_TYPES } from "./deps";
|
|
@@ -117,6 +124,19 @@ export type { JobsFile, JobDef } from "./jobs";
|
|
|
117
124
|
export type { TriggersFile, TriggerDef, EntityEvent } from "./triggers";
|
|
118
125
|
export type { WebhooksFile, WebhookSubscription, WebhookPayload } from "./webhooks";
|
|
119
126
|
export type { PrintTemplatesFile, PrintTemplateDef, PrintPageSettings, PrintMargins } from "./print-templates";
|
|
127
|
+
export type {
|
|
128
|
+
CardLayoutsFile,
|
|
129
|
+
CardLayoutDef,
|
|
130
|
+
CardLayout,
|
|
131
|
+
CardSection,
|
|
132
|
+
CardSetConfig,
|
|
133
|
+
CardTabRef,
|
|
134
|
+
CardFieldEntry,
|
|
135
|
+
CardFieldDef,
|
|
136
|
+
ColumnGroupSection,
|
|
137
|
+
SetSection,
|
|
138
|
+
TabGroupSection,
|
|
139
|
+
} from "./card-layouts";
|
|
120
140
|
export type { SeedDataFile } from "./seed-data";
|
|
121
141
|
export type { ActionsFile, ActionDef, ActionExecutionMode } from "./actions";
|
|
122
142
|
|
package/src/manifest.ts
CHANGED
|
@@ -44,6 +44,8 @@ export interface ManifestDef {
|
|
|
44
44
|
dependencies?: Record<string, ModuleDependency>;
|
|
45
45
|
/** Default audit history mode for this module's entities. */
|
|
46
46
|
auditHistory?: "none" | "minimal" | "full";
|
|
47
|
+
/** Default for `comments` on this module's entities; each entity may override. */
|
|
48
|
+
comments?: boolean;
|
|
47
49
|
/** Entity code → relative path of its JSON file (dotted keys = extensions). */
|
|
48
50
|
entities?: Record<string, string>;
|
|
49
51
|
/** Module category for display (e.g. 'Integration', 'Finance'). */
|
package/src/reports.ts
CHANGED
|
@@ -128,8 +128,12 @@ export interface Dataset {
|
|
|
128
128
|
datasetType: "Q" | "S";
|
|
129
129
|
/** Used when `datasetType` is 'Q'. */
|
|
130
130
|
query?: ReportQuery;
|
|
131
|
-
/**
|
|
132
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Used when `datasetType` is 'S': the stored-procedure code, as
|
|
133
|
+
* `logic/stored_procedures.json` keys it — not the PostgreSQL function name,
|
|
134
|
+
* and never schema-qualified. `module.spCd` binds a dependency's procedure.
|
|
135
|
+
*/
|
|
136
|
+
spCd?: string;
|
|
133
137
|
/** Optional column metadata overrides: field code → override. */
|
|
134
138
|
columnsDef?: Record<string, ColumnDef>;
|
|
135
139
|
/**
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Stored procedures — authoring shape of `logic/stored_procedures.json`.
|
|
2
|
+
// Mirror of stored_procedures.schema.json.
|
|
3
|
+
//
|
|
4
|
+
// Each entry registers one PostgreSQL function as a procedure a report dataset
|
|
5
|
+
// binds through `datasetType: "S"` and `spCd`. The SQL creating the function
|
|
6
|
+
// ships separately, under `logic/reports/*.sql`; this file names the function
|
|
7
|
+
// that script creates, never the script.
|
|
8
|
+
|
|
9
|
+
/** `logic/stored_procedures.json` — keyed by stored-procedure code (`sp_cd`). */
|
|
10
|
+
export type StoredProceduresFile = Record<string, StoredProcedureDef>;
|
|
11
|
+
|
|
12
|
+
/** One stored-procedure declaration. */
|
|
13
|
+
export interface StoredProcedureDef {
|
|
14
|
+
/** Label in the report editor's procedure picker. Defaults to the code. */
|
|
15
|
+
description?: string;
|
|
16
|
+
/** Schema holding the function. Defaults to the module's own schema. */
|
|
17
|
+
schemaName?: string;
|
|
18
|
+
/**
|
|
19
|
+
* The function's own name, unqualified — `report.run` calls
|
|
20
|
+
* `SELECT * FROM "schemaName"."functionName"(...)`. Required: it is the one
|
|
21
|
+
* fact this file exists to record, and install fails naming it when absent.
|
|
22
|
+
*/
|
|
23
|
+
functionName: string;
|
|
24
|
+
/** The function is set-returning — the only shape `report.run` projects. */
|
|
25
|
+
returnsTable?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The call signature, in order. `report.run` passes exactly one positional
|
|
28
|
+
* argument per entry and nothing else — no folder, no user — so a function
|
|
29
|
+
* taking `p_folder_uid` / `p_user_id` can never be called.
|
|
30
|
+
*/
|
|
31
|
+
params?: SpParamDef[];
|
|
32
|
+
/**
|
|
33
|
+
* Result columns. Omit the block and install derives them from the function's
|
|
34
|
+
* own `RETURNS TABLE` / OUT column names; a declared list is used as written
|
|
35
|
+
* and never merged with the signature.
|
|
36
|
+
*/
|
|
37
|
+
columns?: SpColumnDef[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** One declared argument of the procedure. */
|
|
41
|
+
export interface SpParamDef {
|
|
42
|
+
/** Parameter code, conventionally the function's own argument name. */
|
|
43
|
+
paramCd: string;
|
|
44
|
+
/**
|
|
45
|
+
* PostgreSQL type of the argument — what binds the value, carried even when
|
|
46
|
+
* the value is null so an omitted optional argument arrives as a typed null.
|
|
47
|
+
* Case-insensitive, and a type modifier is ignored (`numeric(18,2)`).
|
|
48
|
+
* Defaults to `bigint`, so declare it for every argument that is not one.
|
|
49
|
+
*/
|
|
50
|
+
pgType?: string;
|
|
51
|
+
/** Control copied into the report param on bind. Derived from `pgType` when omitted. */
|
|
52
|
+
fieldTypeCd?: string;
|
|
53
|
+
label?: string;
|
|
54
|
+
/** Default true. Give every optional one `DEFAULT NULL` in the signature. */
|
|
55
|
+
required?: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** One declared result column of the procedure. */
|
|
59
|
+
export interface SpColumnDef {
|
|
60
|
+
/** Result column name as the function returns it. Unique within the procedure. */
|
|
61
|
+
columnCd: string;
|
|
62
|
+
/** Column header. Defaults to the code. */
|
|
63
|
+
label?: string;
|
|
64
|
+
fieldTypeCd?: string;
|
|
65
|
+
baseDatatypeCd?: string;
|
|
66
|
+
/** Display order. Defaults to declaration order in steps of 10. */
|
|
67
|
+
orderNum?: number;
|
|
68
|
+
/** Entity this column links to, making the value clickable. */
|
|
69
|
+
refEntityCd?: string;
|
|
70
|
+
/** Column holding the FK value for that link, when it is not this one. */
|
|
71
|
+
refColumnCd?: string;
|
|
72
|
+
width?: number;
|
|
73
|
+
/** Control parameters, the same shape an entity column's `params` takes. */
|
|
74
|
+
params?: Record<string, unknown>;
|
|
75
|
+
}
|