@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 CHANGED
@@ -5,6 +5,27 @@ All notable changes to `@dforge-core/metadata` are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this package adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.0.28] — 2026-09-22
9
+
10
+ ### Added
11
+
12
+ - **`schemas/stored_procedures.schema.json` and the types mirroring it** —
13
+ `StoredProceduresFile`, `StoredProcedureDef`, `SpParamDef`, `SpColumnDef`. The
14
+ authoring shape of `logic/stored_procedures.json`, which had no schema and no type
15
+ anywhere: a report dataset could say `datasetType: "S"`, and the validator could
16
+ demand the file, but nothing described what belongs in it. `functionName` is the
17
+ required field — the function's own name, not the `logic/reports/*.sql` script that
18
+ creates it.
19
+
20
+ ### Fixed
21
+
22
+ - **A report dataset binds a stored procedure through `spCd`, not `procedureName`.**
23
+ Both `Dataset.procedureName` and the `procedureName` property in
24
+ `reports.schema.json` named a field the platform has never read — and because the
25
+ dataset schema is `additionalProperties: false`, editor validation *rejected* the
26
+ real one. Anyone authoring an SP dataset against the schema was told the correct
27
+ field was invalid and the wrong one was fine.
28
+
8
29
  ## [0.0.26] — 2026-09-15
9
30
 
10
31
  ### Added
package/dist/index.d.ts CHANGED
@@ -673,8 +673,8 @@ interface AccumulationConfig {
673
673
  sign?: SignConfig;
674
674
  autoCreateBalance?: boolean;
675
675
  allowNegative?: boolean;
676
- /** Document fields locked once posted. */
677
- lockedFields?: string[];
676
+ /** Document fields locked once posted. Required; `["*"]` freezes the whole row. */
677
+ lockedFields: string[];
678
678
  }
679
679
  /** One registry target within an L-column's `registries` array. */
680
680
  interface LedgerRegistryEntry {
@@ -708,6 +708,8 @@ interface EntityDef {
708
708
  viewSql?: string;
709
709
  /** Display pattern using column placeholders, e.g. "{first_name} {last_name}". */
710
710
  toString?: string;
711
+ /** Records of this entity accept comments (composer + thread on the card). */
712
+ comments?: boolean;
711
713
  /** Traits expanded at install time. */
712
714
  traits?: TraitCd[];
713
715
  /** Column definitions keyed by column code. Optional when a trait (e.g. `period`) supplies all columns. */
@@ -756,7 +758,7 @@ declare function getIdentityKeys(entity: EntityDef, entityCode: string): string[
756
758
  declare function getPrimaryKeys(entity: EntityDef, entityCode: string): string[];
757
759
 
758
760
  /** `viewType` values for `ui/data_views.json`. Source: data_views.schema.json. */
759
- type ViewType = "grid" | "list" | "kanban" | "calendar" | "gallery" | "tree-grid" | "diagram" | "master-detail" | "library" | "matrix";
761
+ type ViewType = "grid" | "list" | "kanban" | "calendar" | "gallery" | "tree-grid" | "diagram" | "library" | "matrix";
760
762
  /** Friendly picker list of the view kinds. */
761
763
  declare const dataViewKinds: readonly NamedKind[];
762
764
  /** A column in a data source: shorthand string code or a configured object. */
@@ -776,7 +778,7 @@ interface DataSource {
776
778
  entityCode: string;
777
779
  /** Nesting level (0 = root, 1+ = detail). */
778
780
  level?: number;
779
- /** Human-readable label (used in master-detail tabs). */
781
+ /** Human-readable label for this data source. */
780
782
  label?: string;
781
783
  /** Column configuration. */
782
784
  columns?: ViewColumn[];
@@ -835,7 +837,7 @@ interface DataViewDef {
835
837
  /** Bootstrap icon class (e.g. 'bi-bounding-box'). */
836
838
  icon?: string;
837
839
  description?: string;
838
- /** Data sources (at least one; master-detail needs two). */
840
+ /** Data sources (at least one). Only the first is rendered today. */
839
841
  dataSources: DataSource[];
840
842
  /** Default filter applied to all sources unless one declares its own. */
841
843
  filter?: Filter;
@@ -945,8 +947,12 @@ interface Dataset {
945
947
  datasetType: "Q" | "S";
946
948
  /** Used when `datasetType` is 'Q'. */
947
949
  query?: ReportQuery;
948
- /** Used when `datasetType` is 'S'. */
949
- procedureName?: string;
950
+ /**
951
+ * Used when `datasetType` is 'S': the stored-procedure code, as
952
+ * `logic/stored_procedures.json` keys it — not the PostgreSQL function name,
953
+ * and never schema-qualified. `module.spCd` binds a dependency's procedure.
954
+ */
955
+ spCd?: string;
950
956
  /** Optional column metadata overrides: field code → override. */
951
957
  columnsDef?: Record<string, ColumnDef>;
952
958
  /**
@@ -1021,6 +1027,71 @@ interface ReportDef {
1021
1027
  /** A `ui/reports.json` file: report code → definition. */
1022
1028
  type ReportsFile = Record<string, ReportDef>;
1023
1029
 
1030
+ /** `logic/stored_procedures.json` — keyed by stored-procedure code (`sp_cd`). */
1031
+ type StoredProceduresFile = Record<string, StoredProcedureDef>;
1032
+ /** One stored-procedure declaration. */
1033
+ interface StoredProcedureDef {
1034
+ /** Label in the report editor's procedure picker. Defaults to the code. */
1035
+ description?: string;
1036
+ /** Schema holding the function. Defaults to the module's own schema. */
1037
+ schemaName?: string;
1038
+ /**
1039
+ * The function's own name, unqualified — `report.run` calls
1040
+ * `SELECT * FROM "schemaName"."functionName"(...)`. Required: it is the one
1041
+ * fact this file exists to record, and install fails naming it when absent.
1042
+ */
1043
+ functionName: string;
1044
+ /** The function is set-returning — the only shape `report.run` projects. */
1045
+ returnsTable?: boolean;
1046
+ /**
1047
+ * The call signature, in order. `report.run` passes exactly one positional
1048
+ * argument per entry and nothing else — no folder, no user — so a function
1049
+ * taking `p_folder_uid` / `p_user_id` can never be called.
1050
+ */
1051
+ params?: SpParamDef[];
1052
+ /**
1053
+ * Result columns. Omit the block and install derives them from the function's
1054
+ * own `RETURNS TABLE` / OUT column names; a declared list is used as written
1055
+ * and never merged with the signature.
1056
+ */
1057
+ columns?: SpColumnDef[];
1058
+ }
1059
+ /** One declared argument of the procedure. */
1060
+ interface SpParamDef {
1061
+ /** Parameter code, conventionally the function's own argument name. */
1062
+ paramCd: string;
1063
+ /**
1064
+ * PostgreSQL type of the argument — what binds the value, carried even when
1065
+ * the value is null so an omitted optional argument arrives as a typed null.
1066
+ * Case-insensitive, and a type modifier is ignored (`numeric(18,2)`).
1067
+ * Defaults to `bigint`, so declare it for every argument that is not one.
1068
+ */
1069
+ pgType?: string;
1070
+ /** Control copied into the report param on bind. Derived from `pgType` when omitted. */
1071
+ fieldTypeCd?: string;
1072
+ label?: string;
1073
+ /** Default true. Give every optional one `DEFAULT NULL` in the signature. */
1074
+ required?: boolean;
1075
+ }
1076
+ /** One declared result column of the procedure. */
1077
+ interface SpColumnDef {
1078
+ /** Result column name as the function returns it. Unique within the procedure. */
1079
+ columnCd: string;
1080
+ /** Column header. Defaults to the code. */
1081
+ label?: string;
1082
+ fieldTypeCd?: string;
1083
+ baseDatatypeCd?: string;
1084
+ /** Display order. Defaults to declaration order in steps of 10. */
1085
+ orderNum?: number;
1086
+ /** Entity this column links to, making the value clickable. */
1087
+ refEntityCd?: string;
1088
+ /** Column holding the FK value for that link, when it is not this one. */
1089
+ refColumnCd?: string;
1090
+ width?: number;
1091
+ /** Control parameters, the same shape an entity column's `params` takes. */
1092
+ params?: Record<string, unknown>;
1093
+ }
1094
+
1024
1095
  /** Author block on a manifest. */
1025
1096
  interface ManifestAuthor {
1026
1097
  name: string;
@@ -1064,6 +1135,8 @@ interface ManifestDef {
1064
1135
  dependencies?: Record<string, ModuleDependency>;
1065
1136
  /** Default audit history mode for this module's entities. */
1066
1137
  auditHistory?: "none" | "minimal" | "full";
1138
+ /** Default for `comments` on this module's entities; each entity may override. */
1139
+ comments?: boolean;
1067
1140
  /** Entity code → relative path of its JSON file (dotted keys = extensions). */
1068
1141
  entities?: Record<string, string>;
1069
1142
  /** Module category for display (e.g. 'Integration', 'Finance'). */
@@ -1422,6 +1495,95 @@ interface PrintTemplateDef {
1422
1495
  /** A `ui/print_templates.json` file: template_cd → definition. */
1423
1496
  type PrintTemplatesFile = Record<string, PrintTemplateDef>;
1424
1497
 
1498
+ /** A field in a card section — either a bare column code or pixel sizing with it. */
1499
+ type CardFieldEntry = string | CardFieldDef;
1500
+ interface CardFieldDef {
1501
+ column_cd: string;
1502
+ /** Field width in px. */
1503
+ width?: number;
1504
+ /** Field height in px — for multiline/textarea fields. */
1505
+ height?: number;
1506
+ }
1507
+ /** A group of fields laid out in 1, 2 or 3 columns. */
1508
+ interface ColumnGroupSection {
1509
+ type: "columnGroup";
1510
+ code: string;
1511
+ /** Section heading, in the module's authoring language. The installer gives it an
1512
+ * `entity_column_group` row keyed on this section's `code`, so
1513
+ * `translations/<locale>.json` localizes it under
1514
+ * `entities.<entity>.columnGroups.<code>.label` and the card renders that instead. */
1515
+ label?: string;
1516
+ columns: CardFieldEntry[];
1517
+ /** Field columns across the group (1-3). Defaults to the card's own setting. */
1518
+ cols?: number;
1519
+ }
1520
+ /**
1521
+ * An embedded detail grid for a 1:N set column — the master/detail building
1522
+ * block. The label comes from the set column's own metadata.
1523
+ */
1524
+ interface SetSection {
1525
+ type: "set";
1526
+ code: string;
1527
+ /** Set column code on this entity (columnType 'S'). */
1528
+ setField: string;
1529
+ }
1530
+ /** Reference to a tab item: a columnGroup section's code, or a set column's code. */
1531
+ interface CardTabRef {
1532
+ type: "section" | "set";
1533
+ code: string;
1534
+ }
1535
+ /** A tab bar whose tabs are other sections — several detail grids without one long form. */
1536
+ interface TabGroupSection {
1537
+ type: "tabGroup";
1538
+ code: string;
1539
+ tabs: CardTabRef[];
1540
+ }
1541
+ type CardSection = ColumnGroupSection | SetSection | TabGroupSection;
1542
+ /** Per-set-field renderer choice, keyed by the set column code. */
1543
+ interface CardSetConfig {
1544
+ viewType?: "grid" | "list";
1545
+ /** Opaque per-renderer options, passed verbatim to the set registration. */
1546
+ options?: Record<string, unknown>;
1547
+ }
1548
+ /** The layout body, stored verbatim into `dForge.entity_view_layout.layout`. */
1549
+ interface CardLayout {
1550
+ sections: CardSection[];
1551
+ sets?: Record<string, CardSetConfig>;
1552
+ }
1553
+ /**
1554
+ * A module-shipped card layout (value in the card_layouts map; the key is the
1555
+ * layout name).
1556
+ *
1557
+ * Rows written from here carry `module_id`, so the installer recreates them on
1558
+ * every install and removes them on uninstall. A layout the tenant drew in the
1559
+ * card editor has `module_id` NULL and is never touched.
1560
+ */
1561
+ interface CardLayoutDef {
1562
+ /**
1563
+ * Entity code the layout belongs to. Unqualified means this module owns the
1564
+ * entity; `module.entity` targets another module's (the bridge case).
1565
+ */
1566
+ entity: string;
1567
+ /**
1568
+ * Entity view the layout hangs off. Defaults to `"default"` — the same
1569
+ * fallback the runtime uses for an entity with no folder binding of its own.
1570
+ * Matched against the entity's declared views case-insensitively, and filed
1571
+ * under their spelling.
1572
+ */
1573
+ view?: string;
1574
+ /**
1575
+ * Whether this layout opens by default. Honoured on FIRST install only, and
1576
+ * only when the view has no default yet: once a tenant has chosen their own,
1577
+ * an upgrade does not take it back.
1578
+ */
1579
+ isDefault?: boolean;
1580
+ /** Human-readable note for the package author. Not stored. */
1581
+ description?: string;
1582
+ layout: CardLayout;
1583
+ }
1584
+ /** `ui/card_layouts.json` — layout name → definition. */
1585
+ type CardLayoutsFile = Record<string, CardLayoutDef>;
1586
+
1425
1587
  /** A seed-data file: records to insert into one entity. */
1426
1588
  interface SeedDataFile {
1427
1589
  /** Target entity code. */
@@ -1435,4 +1597,4 @@ declare const flagDefs: readonly {
1435
1597
  label: string;
1436
1598
  }[];
1437
1599
 
1438
- export { AGG_TYPE_LIST, type AccumulationConfig, AggType, type AlignType, type BaseDatatypeCd, type CalendarViewConfig, type ColumnDef, type ColumnTypeCd, type ColumnTypeDef, DEP_COLUMN_TYPES, type DataSource, type DataViewDef, type DataViewsFile, type Dataset, type DepColumn, type DepColumnMode, type DepColumnType, type DepEntity, type DepProvenance, type DepProvenanceKind, type DepsFile, type DeriveOptions, type DiagramViewConfig, type DomainDef, type DomainsFile, type EntityDef, type EntityEvent, type EntityReference, type EntityViewColumnDef, type EntityViewDef, FILTER_GROUP_OPERATORS, FILTER_OPERATORS, type FieldDef, type FieldLink, type FieldOption, type FieldTypeCd, type FieldTypeDef, type Filter, type FilterCondition, type FilterGroup, type FilterGroupOperator, type FilterOperator, type FlagCd, type FolderDef, type FolderEntityBinding, type FoldersFile, type JobDef, type JobsFile, type KanbanViewConfig, type LedgerRegistryEntry, type ListLevelConfig, type ListViewConfig, type ManifestAuthor, type ManifestDef, type MenuDef, type MenuItemDef, type MenuItemType, type MenusFile, type ModuleDependency, type ModuleFeature, NUMERIC_TOTAL, type NamedKind, type NumberSequenceDef, type ParamDef, type ParamDefBase, type PeriodConfig, type PrintMargins, type PrintPageSettings, type PrintTemplateDef, type PrintTemplatesFile, type ReportDef, type ReportEntityAttachment, type ReportLayout, type ReportPanel, type ReportQuery, type ReportsFile, type RoleDef, type RolesFile, type SeedDataFile, type SettingBaseDatatype, type SettingDef, type SettingsFile, type SignConfig, type SortClause, type TraitCd, type TraitDef, type TraitFieldConflict, type TraitsFile, type TreeGridViewConfig, type TriggerDef, type TriggersFile, type ViewColumn, type ViewType, type VizType, type WebhookPayload, type WebhookSubscription, type WebhooksFile, baseDatatypes, baseToDbDatatype, chartTypes, columnTypes, dataViewKinds, defaultParams, deriveBaseDatatype, deriveDbDatatype, expandTrait, expandTraits, fieldTypeCds, fieldTypes, fieldTypesByColumnType, flagDefs, getColumnType, getFieldType, getIdentityKeys, getLinks, getPrimaryKeys, getTrait, isFieldTypeCd, traitFieldConflicts, traits, vizTypes };
1600
+ export { AGG_TYPE_LIST, type AccumulationConfig, AggType, type AlignType, type BaseDatatypeCd, type CalendarViewConfig, type CardFieldDef, type CardFieldEntry, type CardLayout, type CardLayoutDef, type CardLayoutsFile, type CardSection, type CardSetConfig, type CardTabRef, type ColumnDef, type ColumnGroupSection, type ColumnTypeCd, type ColumnTypeDef, DEP_COLUMN_TYPES, type DataSource, type DataViewDef, type DataViewsFile, type Dataset, type DepColumn, type DepColumnMode, type DepColumnType, type DepEntity, type DepProvenance, type DepProvenanceKind, type DepsFile, type DeriveOptions, type DiagramViewConfig, type DomainDef, type DomainsFile, type EntityDef, type EntityEvent, type EntityReference, type EntityViewColumnDef, type EntityViewDef, FILTER_GROUP_OPERATORS, FILTER_OPERATORS, type FieldDef, type FieldLink, type FieldOption, type FieldTypeCd, type FieldTypeDef, type Filter, type FilterCondition, type FilterGroup, type FilterGroupOperator, type FilterOperator, type FlagCd, type FolderDef, type FolderEntityBinding, type FoldersFile, type JobDef, type JobsFile, type KanbanViewConfig, type LedgerRegistryEntry, type ListLevelConfig, type ListViewConfig, type ManifestAuthor, type ManifestDef, type MenuDef, type MenuItemDef, type MenuItemType, type MenusFile, type ModuleDependency, type ModuleFeature, NUMERIC_TOTAL, type NamedKind, type NumberSequenceDef, type ParamDef, type ParamDefBase, type PeriodConfig, type PrintMargins, type PrintPageSettings, type PrintTemplateDef, type PrintTemplatesFile, type ReportDef, type ReportEntityAttachment, type ReportLayout, type ReportPanel, type ReportQuery, type ReportsFile, type RoleDef, type RolesFile, type SeedDataFile, type SetSection, type SettingBaseDatatype, type SettingDef, type SettingsFile, type SignConfig, type SortClause, type SpColumnDef, type SpParamDef, type StoredProcedureDef, type StoredProceduresFile, type TabGroupSection, type TraitCd, type TraitDef, type TraitFieldConflict, type TraitsFile, type TreeGridViewConfig, type TriggerDef, type TriggersFile, type ViewColumn, type ViewType, type VizType, type WebhookPayload, type WebhookSubscription, type WebhooksFile, baseDatatypes, baseToDbDatatype, chartTypes, columnTypes, dataViewKinds, defaultParams, deriveBaseDatatype, deriveDbDatatype, expandTrait, expandTraits, fieldTypeCds, fieldTypes, fieldTypesByColumnType, flagDefs, getColumnType, getFieldType, getIdentityKeys, getLinks, getPrimaryKeys, getTrait, isFieldTypeCd, traitFieldConflicts, traits, vizTypes };
package/dist/index.js CHANGED
@@ -366,7 +366,6 @@ var dataViewKinds = [
366
366
  { cd: "gallery", name: "Gallery" },
367
367
  { cd: "tree-grid", name: "Tree Grid" },
368
368
  { cd: "diagram", name: "Diagram" },
369
- { cd: "master-detail", name: "Master / Detail" },
370
369
  { cd: "library", name: "Library" },
371
370
  { cd: "matrix", name: "Matrix" }
372
371
  ];