@dforge-core/metadata 0.0.1
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/actions.d.ts +31 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +7 -0
- package/dist/actions.js.map +1 -0
- package/dist/aggregation.d.ts +13 -0
- package/dist/aggregation.d.ts.map +1 -0
- package/dist/aggregation.js +17 -0
- package/dist/aggregation.js.map +1 -0
- package/dist/base-datatypes.d.ts +5 -0
- package/dist/base-datatypes.d.ts.map +1 -0
- package/dist/base-datatypes.js +49 -0
- package/dist/base-datatypes.js.map +1 -0
- package/dist/column-types.d.ts +5 -0
- package/dist/column-types.d.ts.map +1 -0
- package/dist/column-types.js +18 -0
- package/dist/column-types.js.map +1 -0
- package/dist/data-views.d.ts +95 -0
- package/dist/data-views.d.ts.map +1 -0
- package/dist/data-views.js +17 -0
- package/dist/data-views.js.map +1 -0
- package/dist/derive.d.ts +19 -0
- package/dist/derive.d.ts.map +1 -0
- package/dist/derive.js +51 -0
- package/dist/derive.js.map +1 -0
- package/dist/entity.d.ts +110 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/entity.js +7 -0
- package/dist/entity.js.map +1 -0
- package/dist/field-types.d.ts +260 -0
- package/dist/field-types.d.ts.map +1 -0
- package/dist/field-types.js +55 -0
- package/dist/field-types.js.map +1 -0
- package/dist/filter.d.ts +26 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +7 -0
- package/dist/filter.js.map +1 -0
- package/dist/folders.d.ts +32 -0
- package/dist/folders.d.ts.map +1 -0
- package/dist/folders.js +6 -0
- package/dist/folders.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs.d.ts +32 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +3 -0
- package/dist/jobs.js.map +1 -0
- package/dist/manifest.d.ts +53 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +4 -0
- package/dist/manifest.js.map +1 -0
- package/dist/menus.d.ts +32 -0
- package/dist/menus.d.ts.map +1 -0
- package/dist/menus.js +3 -0
- package/dist/menus.js.map +1 -0
- package/dist/print-templates.d.ts +36 -0
- package/dist/print-templates.d.ts.map +1 -0
- package/dist/print-templates.js +4 -0
- package/dist/print-templates.js.map +1 -0
- package/dist/reports.d.ts +84 -0
- package/dist/reports.d.ts.map +1 -0
- package/dist/reports.js +24 -0
- package/dist/reports.js.map +1 -0
- package/dist/roles.d.ts +10 -0
- package/dist/roles.d.ts.map +1 -0
- package/dist/roles.js +3 -0
- package/dist/roles.js.map +1 -0
- package/dist/seed-data.d.ts +8 -0
- package/dist/seed-data.d.ts.map +1 -0
- package/dist/seed-data.js +4 -0
- package/dist/seed-data.js.map +1 -0
- package/dist/settings.d.ts +26 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +3 -0
- package/dist/settings.js.map +1 -0
- package/dist/traits.d.ts +14 -0
- package/dist/traits.d.ts.map +1 -0
- package/dist/traits.js +121 -0
- package/dist/traits.js.map +1 -0
- package/dist/triggers.d.ts +24 -0
- package/dist/triggers.d.ts.map +1 -0
- package/dist/triggers.js +3 -0
- package/dist/triggers.js.map +1 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks.d.ts +31 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +3 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +54 -0
- package/src/actions.ts +38 -0
- package/src/aggregation.ts +21 -0
- package/src/base-datatypes.ts +53 -0
- package/src/column-types.ts +22 -0
- package/src/data-views.ts +139 -0
- package/src/derive.ts +63 -0
- package/src/entity.ts +124 -0
- package/src/field-types.ts +68 -0
- package/src/filter.ts +34 -0
- package/src/folders.ts +39 -0
- package/src/index.ts +109 -0
- package/src/jobs.ts +34 -0
- package/src/manifest.ts +54 -0
- package/src/menus.ts +36 -0
- package/src/print-templates.ts +41 -0
- package/src/reports.ts +111 -0
- package/src/roles.ts +12 -0
- package/src/seed-data.ts +10 -0
- package/src/settings.ts +29 -0
- package/src/traits.ts +127 -0
- package/src/triggers.ts +27 -0
- package/src/types.ts +177 -0
- package/src/webhooks.ts +35 -0
package/src/filter.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Canonical dForge filter expression.
|
|
2
|
+
//
|
|
3
|
+
// One shape shared by data views, reports, folders (row-level security) and the
|
|
4
|
+
// API: either a single condition `{c, o, v}` or a group `{g, i: [...]}`. Mirror
|
|
5
|
+
// of the `filter` $def repeated across data_views / reports / folders schemas.
|
|
6
|
+
|
|
7
|
+
/** A single filter condition. */
|
|
8
|
+
export interface FilterCondition {
|
|
9
|
+
/** Column code (supports dot navigation: 'customer.name'). */
|
|
10
|
+
c: string;
|
|
11
|
+
/** Operator: eq, neq, =, !=, gt, gtEq, lt, ltEq, in, nIn, like, isNull, … */
|
|
12
|
+
o: string;
|
|
13
|
+
/** Comparison value: scalar, array (in/nIn) or a `@param_code` reference. */
|
|
14
|
+
v?: unknown;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** A boolean group of nested conditions/sub-groups. */
|
|
18
|
+
export interface FilterGroup {
|
|
19
|
+
/** Group combinator. */
|
|
20
|
+
g: "and" | "or";
|
|
21
|
+
/** Group items: nested conditions or sub-groups. */
|
|
22
|
+
i: Filter[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A filter is either a single condition or a group. */
|
|
26
|
+
export type Filter = FilterCondition | FilterGroup;
|
|
27
|
+
|
|
28
|
+
/** A sort clause `{ c, d }` as used by reports / per-source order. */
|
|
29
|
+
export interface SortClause {
|
|
30
|
+
/** Column code. */
|
|
31
|
+
c: string;
|
|
32
|
+
/** Sort direction (default: asc). */
|
|
33
|
+
d?: "asc" | "desc";
|
|
34
|
+
}
|
package/src/folders.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Folders — authoring shape of `folders.json`. Mirror of folders.schema.json.
|
|
2
|
+
//
|
|
3
|
+
// The file IS the root folder (not a map keyed by code); sub-folders live under
|
|
4
|
+
// `children`, keyed by folder code.
|
|
5
|
+
|
|
6
|
+
import type { Filter } from "./filter";
|
|
7
|
+
|
|
8
|
+
/** Per-entity binding within a folder. */
|
|
9
|
+
export interface FolderEntityBinding {
|
|
10
|
+
/** Data view code to use in this folder (commonly 'default'). */
|
|
11
|
+
viewName?: string;
|
|
12
|
+
/** Enable the quick-add (+) button for this entity here. */
|
|
13
|
+
quickAdd?: boolean;
|
|
14
|
+
/** Row-level filter: a SQL expression string or a canonical filter object. */
|
|
15
|
+
rowFilter?: string | Filter;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A folder node (the folders.json root, and each entry under `children`). */
|
|
19
|
+
export interface FolderDef {
|
|
20
|
+
label?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
/** Parent folder code (only used by sparse-tree imports; usually omitted). */
|
|
23
|
+
parentCode?: string | null;
|
|
24
|
+
/** URL-friendly folder path override. */
|
|
25
|
+
folderPath?: string;
|
|
26
|
+
/** Accent color (hex, e.g. '#2196F3'). */
|
|
27
|
+
color?: string;
|
|
28
|
+
/** Bootstrap icon class (e.g. 'bi-folder'). */
|
|
29
|
+
icon?: string;
|
|
30
|
+
/** Inherit security rights from the parent folder (default true). */
|
|
31
|
+
inheritSecurity?: boolean;
|
|
32
|
+
/** Entity code → folder-entity binding. */
|
|
33
|
+
entities?: Record<string, FolderEntityBinding>;
|
|
34
|
+
/** Nested folders keyed by sub-folder code (recursive). */
|
|
35
|
+
children?: Record<string, FolderDef>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A `folders.json` file: the root folder itself. */
|
|
39
|
+
export type FoldersFile = FolderDef;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// @dforge-core/metadata — canonical dForge authoring registries + module-file types.
|
|
2
|
+
//
|
|
3
|
+
// Single source of truth for:
|
|
4
|
+
// • registries — field types, base datatypes, column types, traits, data-view
|
|
5
|
+
// kinds, report viz/chart types, plus helpers that derive physical metadata
|
|
6
|
+
// from a friendly field-type choice;
|
|
7
|
+
// • structural types — the authoring shape of every module-package file
|
|
8
|
+
// (manifest, entities, data views, reports, menus, folders, roles, settings,
|
|
9
|
+
// jobs, triggers, webhooks, print templates, seed data, actions), mirrored
|
|
10
|
+
// from the JSON schemas under docs/schemas/.
|
|
11
|
+
//
|
|
12
|
+
// No runtime dependencies; safe to import from editors, the web app, the CLI,
|
|
13
|
+
// the MCP server and the VS Code extension.
|
|
14
|
+
|
|
15
|
+
// ── Shared core types & registries ──────────────────────────────────────────
|
|
16
|
+
export type {
|
|
17
|
+
AlignType,
|
|
18
|
+
BaseDatatypeCd,
|
|
19
|
+
ColumnTypeCd,
|
|
20
|
+
ColumnTypeDef,
|
|
21
|
+
FieldDef,
|
|
22
|
+
FieldLink,
|
|
23
|
+
FieldOption,
|
|
24
|
+
FieldTypeCd,
|
|
25
|
+
FieldTypeDef,
|
|
26
|
+
FlagCd,
|
|
27
|
+
NamedKind,
|
|
28
|
+
TraitDef,
|
|
29
|
+
} from "./types";
|
|
30
|
+
|
|
31
|
+
export { AggType, AGG_TYPE_LIST } from "./aggregation";
|
|
32
|
+
|
|
33
|
+
export { fieldTypes, fieldTypeCds, isFieldTypeCd, getFieldType, fieldTypesByColumnType } from "./field-types";
|
|
34
|
+
export { baseDatatypes, baseToDbDatatype } from "./base-datatypes";
|
|
35
|
+
export { columnTypes, getColumnType } from "./column-types";
|
|
36
|
+
export { traits, getTrait, expandTrait, expandTraits } from "./traits";
|
|
37
|
+
export {
|
|
38
|
+
deriveDbDatatype,
|
|
39
|
+
deriveBaseDatatype,
|
|
40
|
+
defaultParams,
|
|
41
|
+
NUMERIC_TOTAL,
|
|
42
|
+
type DeriveOptions,
|
|
43
|
+
} from "./derive";
|
|
44
|
+
|
|
45
|
+
// ── Shared filter expression (data views / reports / folders / API) ──────────
|
|
46
|
+
export type { Filter, FilterCondition, FilterGroup, SortClause } from "./filter";
|
|
47
|
+
|
|
48
|
+
// ── Module-file structural types ─────────────────────────────────────────────
|
|
49
|
+
export type {
|
|
50
|
+
EntityDef,
|
|
51
|
+
EntityReference,
|
|
52
|
+
NumberSequenceDef,
|
|
53
|
+
PeriodConfig,
|
|
54
|
+
AccumulationConfig,
|
|
55
|
+
SignConfig,
|
|
56
|
+
LedgerRegistryEntry,
|
|
57
|
+
TraitCd,
|
|
58
|
+
} from "./entity";
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
dataViewKinds,
|
|
62
|
+
type DataViewsFile,
|
|
63
|
+
type DataViewDef,
|
|
64
|
+
type DataSource,
|
|
65
|
+
type ViewColumn,
|
|
66
|
+
type ViewType,
|
|
67
|
+
type KanbanViewConfig,
|
|
68
|
+
type CalendarViewConfig,
|
|
69
|
+
type TreeGridViewConfig,
|
|
70
|
+
type ListViewConfig,
|
|
71
|
+
type ListLevelConfig,
|
|
72
|
+
type DiagramViewConfig,
|
|
73
|
+
} from "./data-views";
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
vizTypes,
|
|
77
|
+
chartTypes,
|
|
78
|
+
type ReportsFile,
|
|
79
|
+
type ReportDef,
|
|
80
|
+
type ReportLayout,
|
|
81
|
+
type ReportPanel,
|
|
82
|
+
type Dataset,
|
|
83
|
+
type ReportQuery,
|
|
84
|
+
type ColumnDef,
|
|
85
|
+
type ParamDef,
|
|
86
|
+
type VizType,
|
|
87
|
+
} from "./reports";
|
|
88
|
+
|
|
89
|
+
export type { ManifestDef, ManifestAuthor, ModuleDependency } from "./manifest";
|
|
90
|
+
export type { MenusFile, MenuDef, MenuItemDef, MenuItemType } from "./menus";
|
|
91
|
+
export type { FoldersFile, FolderDef, FolderEntityBinding } from "./folders";
|
|
92
|
+
export type { RolesFile, RoleDef } from "./roles";
|
|
93
|
+
export type { SettingsFile, SettingDef, SettingBaseDatatype } from "./settings";
|
|
94
|
+
export type { JobsFile, JobDef } from "./jobs";
|
|
95
|
+
export type { TriggersFile, TriggerDef, EntityEvent } from "./triggers";
|
|
96
|
+
export type { WebhooksFile, WebhookSubscription, WebhookPayload } from "./webhooks";
|
|
97
|
+
export type { PrintTemplatesFile, PrintTemplateDef, PrintPageSettings, PrintMargins } from "./print-templates";
|
|
98
|
+
export type { SeedDataFile } from "./seed-data";
|
|
99
|
+
export type { ActionsFile, ActionDef, ActionExecutionMode } from "./actions";
|
|
100
|
+
|
|
101
|
+
// Display flag catalog — the only flags valid on an authored field
|
|
102
|
+
// (entity.schema.json `flags` pattern is ^[VIEMH]*$).
|
|
103
|
+
export const flagDefs: readonly { value: "V" | "I" | "E" | "M" | "H"; label: string }[] = [
|
|
104
|
+
{ value: "V", label: "Visible" },
|
|
105
|
+
{ value: "I", label: "Identity" },
|
|
106
|
+
{ value: "E", label: "Editable" },
|
|
107
|
+
{ value: "M", label: "Mandatory" },
|
|
108
|
+
{ value: "H", label: "Hidden" },
|
|
109
|
+
] as const;
|
package/src/jobs.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Scheduled jobs — authoring shape of `logic/jobs.json`. Mirror of jobs.schema.json.
|
|
2
|
+
|
|
3
|
+
/** A single scheduled-job declaration. */
|
|
4
|
+
export interface JobDef {
|
|
5
|
+
/** Unique identifier within the module. */
|
|
6
|
+
code: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
/** Action code in this module the scheduler fires. */
|
|
9
|
+
action: string;
|
|
10
|
+
/** Five-field cron expression (minute granularity). */
|
|
11
|
+
schedule: string;
|
|
12
|
+
/** Static parameters passed to the action as `__params`. */
|
|
13
|
+
params?: Record<string, unknown>;
|
|
14
|
+
/** Hard timeout in seconds (1–3600; > 300 requires class 'long_running'). */
|
|
15
|
+
timeout: number;
|
|
16
|
+
/** Max parallel runs (1–5; default 1). */
|
|
17
|
+
concurrency?: number;
|
|
18
|
+
/** Idempotency key template, e.g. '{job_cd}:{run.month}'. */
|
|
19
|
+
idempotencyKey?: string;
|
|
20
|
+
/** Routing class ('long_running' required for any timeout > 300s). */
|
|
21
|
+
class?: "standard" | "long_running";
|
|
22
|
+
/** IANA tz name overriding the tenant default. */
|
|
23
|
+
timeZone?: string;
|
|
24
|
+
/** Master switch (default true). */
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
/** Soft pause; admin 'trigger now' still works (default false). */
|
|
27
|
+
paused?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A `logic/jobs.json` file. */
|
|
31
|
+
export interface JobsFile {
|
|
32
|
+
/** At most 50 jobs per module. */
|
|
33
|
+
jobs: JobDef[];
|
|
34
|
+
}
|
package/src/manifest.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Module manifest — authoring shape of `manifest.json`.
|
|
2
|
+
// Mirror of manifest.schema.json.
|
|
3
|
+
|
|
4
|
+
/** Author block on a manifest. */
|
|
5
|
+
export interface ManifestAuthor {
|
|
6
|
+
name: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** A dependency value: a semver range, or a partial-dep object. */
|
|
11
|
+
export type ModuleDependency = string | { version: string; entities?: string[] };
|
|
12
|
+
|
|
13
|
+
/** A module package manifest (`manifest.json`). */
|
|
14
|
+
export interface ManifestDef {
|
|
15
|
+
/** Package format version (currently 1). */
|
|
16
|
+
packageFormat: number;
|
|
17
|
+
/** Globally unique module UUID. */
|
|
18
|
+
moduleId: string;
|
|
19
|
+
/** Human-readable module code (becomes the schema name and `module_cd`). */
|
|
20
|
+
code: string;
|
|
21
|
+
/** 'module' (default) or 'pack' (a dependency bundle owning no entities). */
|
|
22
|
+
kind?: "module" | "pack";
|
|
23
|
+
/** Module version (semver). */
|
|
24
|
+
version: string;
|
|
25
|
+
/** Database schema version (semver). */
|
|
26
|
+
dbSchemaVersion: string;
|
|
27
|
+
displayName: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
/** Schema name override (defaults to `code`; system modules use 'dForge'). */
|
|
30
|
+
schemaName?: string;
|
|
31
|
+
/** System module flag (cannot be uninstalled, admin-only). Omit for regular modules. */
|
|
32
|
+
system?: boolean;
|
|
33
|
+
author?: ManifestAuthor;
|
|
34
|
+
/** License identifier (e.g. 'proprietary', 'MIT'). */
|
|
35
|
+
license?: string;
|
|
36
|
+
/** Module code → semver range or partial-dep object. */
|
|
37
|
+
dependencies?: Record<string, ModuleDependency>;
|
|
38
|
+
/** Default audit history mode for this module's entities. */
|
|
39
|
+
auditHistory?: "none" | "minimal" | "full";
|
|
40
|
+
/** Entity code → relative path of its JSON file (dotted keys = extensions). */
|
|
41
|
+
entities?: Record<string, string>;
|
|
42
|
+
/** Module category for display (e.g. 'Integration', 'Finance'). */
|
|
43
|
+
category?: string;
|
|
44
|
+
/** Free-form tags for search/discovery. */
|
|
45
|
+
tags?: string[];
|
|
46
|
+
/** Bootstrap icon class (e.g. 'bi-link-45deg'). */
|
|
47
|
+
icon?: string;
|
|
48
|
+
/** Non-English locales the package promises to translate. */
|
|
49
|
+
supportedLocales?: string[];
|
|
50
|
+
/** Initial creation date (YYYY-MM-DD). Informational. */
|
|
51
|
+
created?: string;
|
|
52
|
+
/** Last manifest edit date (YYYY-MM-DD). Informational. */
|
|
53
|
+
updated?: string;
|
|
54
|
+
}
|
package/src/menus.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Menus — authoring shape of `ui/menus.json`. Mirror of menus.schema.json.
|
|
2
|
+
|
|
3
|
+
/** Menu item type: V=Data View, D=Document, R=Report, null=folder/section. */
|
|
4
|
+
export type MenuItemType = "V" | "D" | "R" | null;
|
|
5
|
+
|
|
6
|
+
/** A menu item; folder/section nodes nest children and omit `itemType`. */
|
|
7
|
+
export interface MenuItemDef {
|
|
8
|
+
itemType?: MenuItemType;
|
|
9
|
+
/** Data view code (when `itemType` is 'V'). */
|
|
10
|
+
dataViewCode?: string;
|
|
11
|
+
/** Document code (when `itemType` is 'D'). */
|
|
12
|
+
documentCode?: string;
|
|
13
|
+
/** Report code (when `itemType` is 'R'). */
|
|
14
|
+
reportCode?: string;
|
|
15
|
+
orderNum?: number;
|
|
16
|
+
/** Display text. */
|
|
17
|
+
label: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
/** Bootstrap icon name. */
|
|
20
|
+
icon?: string;
|
|
21
|
+
/** Child items keyed by item code (folder/section nodes). */
|
|
22
|
+
children?: Record<string, MenuItemDef>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A menu (value in the `ui/menus.json` map). */
|
|
26
|
+
export interface MenuDef {
|
|
27
|
+
label: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
/** Folder codes where this menu is available. */
|
|
30
|
+
folders?: string[];
|
|
31
|
+
/** Menu items keyed by item code. */
|
|
32
|
+
items: Record<string, MenuItemDef>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A `ui/menus.json` file: menu code → definition. */
|
|
36
|
+
export type MenusFile = Record<string, MenuDef>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Print templates — authoring shape of `ui/print_templates.json`.
|
|
2
|
+
// Mirror of print_templates.schema.json.
|
|
3
|
+
|
|
4
|
+
/** Page margins (CSS lengths, e.g. '15mm'). */
|
|
5
|
+
export interface PrintMargins {
|
|
6
|
+
top?: string;
|
|
7
|
+
right?: string;
|
|
8
|
+
bottom?: string;
|
|
9
|
+
left?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Default page geometry applied when printing from the UI. */
|
|
13
|
+
export interface PrintPageSettings {
|
|
14
|
+
size?: "A4" | "letter" | "legal";
|
|
15
|
+
orientation?: "portrait" | "landscape";
|
|
16
|
+
margins?: PrintMargins;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A print template or snippet (value in the print_templates map).
|
|
21
|
+
* `type: 'template'` (default) is entity-bound; `type: 'snippet'` is a
|
|
22
|
+
* module-scoped Liquid partial included via {% include 'module.snippet' %}.
|
|
23
|
+
* Either `file` or `template` must be set (`file` wins when both are present).
|
|
24
|
+
*/
|
|
25
|
+
export interface PrintTemplateDef {
|
|
26
|
+
type?: "template" | "snippet";
|
|
27
|
+
/** Entity code rendered. Required for templates; ignored for snippets. */
|
|
28
|
+
entityCd?: string;
|
|
29
|
+
/** Human-readable label shown in the print menu. */
|
|
30
|
+
description?: string;
|
|
31
|
+
/** Inline Liquid HTML. */
|
|
32
|
+
template?: string;
|
|
33
|
+
/** Relative path under the module's `print_templates/` directory. */
|
|
34
|
+
file?: string;
|
|
35
|
+
/** Inline CSS, or a `.css` filename resolved relative to `print_templates/`. */
|
|
36
|
+
css?: string;
|
|
37
|
+
pageSettings?: PrintPageSettings;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A `ui/print_templates.json` file: template_cd → definition. */
|
|
41
|
+
export type PrintTemplatesFile = Record<string, PrintTemplateDef>;
|
package/src/reports.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Report registries + the authoring shape of a `ui/reports.json` file.
|
|
2
|
+
//
|
|
3
|
+
// `vizTypes` / `chartTypes` are the friendly picker lists; `ReportDef` and
|
|
4
|
+
// friends mirror reports.schema.json so editors/MCP/CLI can build reports.
|
|
5
|
+
|
|
6
|
+
import type { Filter, SortClause } from "./filter";
|
|
7
|
+
import type { NamedKind } from "./types";
|
|
8
|
+
|
|
9
|
+
/** Report visualization types. Source: reports.schema.json (`vizType`). */
|
|
10
|
+
export type VizType = "table" | "chart" | "metric" | "pivot";
|
|
11
|
+
|
|
12
|
+
/** Friendly picker list of report visualization types. */
|
|
13
|
+
export const vizTypes: readonly NamedKind[] = [
|
|
14
|
+
{ cd: "table", name: "Table" },
|
|
15
|
+
{ cd: "chart", name: "Chart" },
|
|
16
|
+
{ cd: "metric", name: "Metric" },
|
|
17
|
+
{ cd: "pivot", name: "Pivot" },
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
/** Chart kinds used by report `config.chartType` (curated; rendered via Chart.js). */
|
|
21
|
+
export const chartTypes: readonly NamedKind[] = [
|
|
22
|
+
{ cd: "bar", name: "Bar" },
|
|
23
|
+
{ cd: "line", name: "Line" },
|
|
24
|
+
{ cd: "area", name: "Area" },
|
|
25
|
+
{ cd: "pie", name: "Pie" },
|
|
26
|
+
{ cd: "donut", name: "Donut" },
|
|
27
|
+
{ cd: "scatter", name: "Scatter" },
|
|
28
|
+
{ cd: "bubble", name: "Bubble" },
|
|
29
|
+
{ cd: "heatmap", name: "Heatmap" },
|
|
30
|
+
{ cd: "funnel", name: "Funnel" },
|
|
31
|
+
] as const;
|
|
32
|
+
|
|
33
|
+
/** A report parameter definition (report- or dataset-level). */
|
|
34
|
+
export interface ParamDef {
|
|
35
|
+
/** Field type code (see settings for the common list). */
|
|
36
|
+
fieldTypeCd: string;
|
|
37
|
+
label?: string;
|
|
38
|
+
/** Display order in the parameter form (falls back to declaration order). */
|
|
39
|
+
orderNum?: number;
|
|
40
|
+
/** Whether the user must provide a value. */
|
|
41
|
+
required?: boolean;
|
|
42
|
+
/** Alternate spelling of `required` used by some modules. Prefer `required`. */
|
|
43
|
+
isRequired?: boolean;
|
|
44
|
+
/** Default value applied when the user doesn't provide one. */
|
|
45
|
+
default?: unknown;
|
|
46
|
+
/** Entity link for lookup-type params. */
|
|
47
|
+
link?: { entity: string; otherKey?: string };
|
|
48
|
+
/** Field-type-specific params. */
|
|
49
|
+
params?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** SQL/entity query for a `datasetType: 'Q'` dataset. */
|
|
53
|
+
export interface ReportQuery {
|
|
54
|
+
/** Source entity code. */
|
|
55
|
+
entityCd: string;
|
|
56
|
+
/** Column codes to select (supports dot navigation: 'customer.name'). */
|
|
57
|
+
columns?: string[];
|
|
58
|
+
filter?: Filter;
|
|
59
|
+
sort?: SortClause[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Per-column metadata override on a dataset. */
|
|
63
|
+
export interface ColumnDef {
|
|
64
|
+
label?: string;
|
|
65
|
+
visible?: boolean;
|
|
66
|
+
width?: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A report dataset (value in the report's `datasets` map). */
|
|
70
|
+
export interface Dataset {
|
|
71
|
+
/** Display label (used in panel headings if no `title`). */
|
|
72
|
+
caption?: string;
|
|
73
|
+
/** Q = SQL/entity query, S = stored procedure. */
|
|
74
|
+
datasetType: "Q" | "S";
|
|
75
|
+
/** Used when `datasetType` is 'Q'. */
|
|
76
|
+
query?: ReportQuery;
|
|
77
|
+
/** Used when `datasetType` is 'S'. */
|
|
78
|
+
procedureName?: string;
|
|
79
|
+
/** Optional column metadata overrides: field code → override. */
|
|
80
|
+
columnsDef?: Record<string, ColumnDef>;
|
|
81
|
+
/** Dataset-level parameters (alternative to report-level `parameters`). */
|
|
82
|
+
params?: Record<string, ParamDef>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** A single visualization panel within the report layout. */
|
|
86
|
+
export interface ReportPanel {
|
|
87
|
+
vizType: VizType;
|
|
88
|
+
/** Dataset code (key in the report's `datasets` map). */
|
|
89
|
+
datasetCd: string;
|
|
90
|
+
title?: string;
|
|
91
|
+
/** Viz-type-specific config (chart → { chartType, categoryCol, … }). */
|
|
92
|
+
config?: Record<string, unknown>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ReportLayout {
|
|
96
|
+
panels: ReportPanel[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** A single report (value in the `ui/reports.json` map). */
|
|
100
|
+
export interface ReportDef {
|
|
101
|
+
/** Human-readable report title. */
|
|
102
|
+
description: string;
|
|
103
|
+
layout: ReportLayout;
|
|
104
|
+
/** Dataset code → dataset definition. */
|
|
105
|
+
datasets: Record<string, Dataset>;
|
|
106
|
+
/** Report-level parameters (alternative to per-dataset `params`). */
|
|
107
|
+
parameters?: Record<string, ParamDef>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** A `ui/reports.json` file: report code → definition. */
|
|
111
|
+
export type ReportsFile = Record<string, ReportDef>;
|
package/src/roles.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Roles — authoring shape of `security/roles.json`. Mirror of roles.schema.json.
|
|
2
|
+
|
|
3
|
+
/** A role with its entity rights (value in the roles map). */
|
|
4
|
+
export interface RoleDef {
|
|
5
|
+
/** Role display name. */
|
|
6
|
+
description: string;
|
|
7
|
+
/** Entity code → rights string. Rights: S/I/U/D/C/E (pattern ^[SIUDCE]*$). */
|
|
8
|
+
rights: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** A `roles.json` file: role code → definition. */
|
|
12
|
+
export type RolesFile = Record<string, RoleDef>;
|
package/src/seed-data.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Seed data — authoring shape of a `seed-data/*.json` file.
|
|
2
|
+
// Mirror of seed_data.schema.json.
|
|
3
|
+
|
|
4
|
+
/** A seed-data file: records to insert into one entity. */
|
|
5
|
+
export interface SeedDataFile {
|
|
6
|
+
/** Target entity code. */
|
|
7
|
+
entityCode: string;
|
|
8
|
+
/** Records to insert; each is a `column_code → value` map. */
|
|
9
|
+
records: Record<string, unknown>[];
|
|
10
|
+
}
|
package/src/settings.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Module settings — authoring shape of `settings.json`. Mirror of settings.schema.json.
|
|
2
|
+
|
|
3
|
+
/** Underlying primitive datatype for a setting. */
|
|
4
|
+
export type SettingBaseDatatype = "string" | "number" | "bool" | "date" | "dateTime" | "time" | "json";
|
|
5
|
+
|
|
6
|
+
/** A single setting definition (value in the settings map). */
|
|
7
|
+
export interface SettingDef {
|
|
8
|
+
/** Field type code (must match a `dforge.field_type` code). */
|
|
9
|
+
fieldTypeCd: string;
|
|
10
|
+
/** Underlying primitive datatype (older settings declare this explicitly). */
|
|
11
|
+
baseDatatypeCd?: SettingBaseDatatype;
|
|
12
|
+
/** Display label (preferred for new settings). */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Display label (older style). Prefer `label`. */
|
|
15
|
+
description?: string;
|
|
16
|
+
/** Alternative older label key. Prefer `label`. */
|
|
17
|
+
desc?: string;
|
|
18
|
+
/** Default value before the user sets one. */
|
|
19
|
+
defaultValue?: unknown;
|
|
20
|
+
/** Formula to evaluate the default (alternative to `defaultValue`). */
|
|
21
|
+
formula?: string;
|
|
22
|
+
/** If true, must be set somewhere in the folder chain for install to proceed. */
|
|
23
|
+
required?: boolean;
|
|
24
|
+
/** Field-type-specific parameters (dropdown options, min/max, lookup link, …). */
|
|
25
|
+
params?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A `settings.json` file: setting code → definition. */
|
|
29
|
+
export type SettingsFile = Record<string, SettingDef>;
|
package/src/traits.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Trait registry — mirror of
|
|
2
|
+
// server/database/system-modules/metadata/traits.json
|
|
3
|
+
//
|
|
4
|
+
// Traits are authoring shortcuts: adding one to an entity injects a fixed set of
|
|
5
|
+
// fields (and sometimes references) at install time. The visual editor offers
|
|
6
|
+
// these as checkboxes and previews the expanded fields, so authors never
|
|
7
|
+
// hand-write `created_date` / `{entity}_id` etc.
|
|
8
|
+
|
|
9
|
+
import type { FieldDef, TraitDef } from "./types";
|
|
10
|
+
|
|
11
|
+
export const traits: readonly TraitDef[] = [
|
|
12
|
+
{
|
|
13
|
+
cd: "identity",
|
|
14
|
+
description: "Primary Key",
|
|
15
|
+
fields: {
|
|
16
|
+
"{entity}_id": { dbDatatype: "cuid", flags: "I", isPk: true, isIdentity: true, isNullable: false, orderNum: 1, description: "{Entity} ID" },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
cd: "audit",
|
|
21
|
+
description: "Creation and update timestamps",
|
|
22
|
+
fields: {
|
|
23
|
+
created_date: { dbDatatype: "timestamptz", fieldTypeCd: "datetime", flags: "I", isNullable: false, formula: "NOW()", orderNum: 9901, description: "Created Date" },
|
|
24
|
+
last_updated: { dbDatatype: "timestamptz", fieldTypeCd: "datetime", flags: "I", isNullable: false, formula: "NOW()", orderNum: 9902, description: "Last Updated" },
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
cd: "audit-full",
|
|
29
|
+
description: "Full audit with user tracking",
|
|
30
|
+
includes: ["audit"],
|
|
31
|
+
fields: {
|
|
32
|
+
created_by: { dbDatatype: "cuid", flags: "I", isNullable: false, orderNum: 9903, description: "Created By User ID" },
|
|
33
|
+
created_by_user: { columnType: "R", fieldTypeCd: "lookup", flags: "I", orderNum: 9904, description: "Created By", link: { entity: "user", thisKey: "created_by", otherKey: "user_id" } },
|
|
34
|
+
last_updated_by: { dbDatatype: "cuid", flags: "I", isNullable: false, orderNum: 9905, description: "Last Updated By User ID" },
|
|
35
|
+
last_updated_by_user: { columnType: "R", fieldTypeCd: "lookup", flags: "I", orderNum: 9906, description: "Last Updated By", link: { entity: "user", thisKey: "last_updated_by", otherKey: "user_id" } },
|
|
36
|
+
},
|
|
37
|
+
references: {
|
|
38
|
+
"FK_{Entity}_CreatedBy": { from: { field: "created_by" }, to: { entity: "user", field: "user_id" } },
|
|
39
|
+
"FK_{Entity}_LastUpdatedBy": { from: { field: "last_updated_by" }, to: { entity: "user", field: "user_id" } },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
cd: "soft-delete",
|
|
44
|
+
description: "Soft delete flag",
|
|
45
|
+
fields: {
|
|
46
|
+
active: { dbDatatype: "bool", fieldTypeCd: "checkbox", flags: "", isNullable: false, formula: "true", orderNum: 9910, description: "Active" },
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
cd: "sorting",
|
|
51
|
+
description: "Display order",
|
|
52
|
+
fields: {
|
|
53
|
+
order_num: { dbDatatype: "int4", fieldTypeCd: "number", flags: "VEM", orderNum: 9920, description: "Order" },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{ cd: "postable", description: "Document posting support (marker trait — actual state managed by A/L columns)", fields: {} },
|
|
57
|
+
{ cd: "accumulation", description: "Accumulation register (marker trait — config in A-type column params)", fields: {} },
|
|
58
|
+
{ cd: "ledger", description: "Double-entry ledger (marker trait — config in L-type column params)", fields: {} },
|
|
59
|
+
{
|
|
60
|
+
cd: "period",
|
|
61
|
+
description: "Period entity with key format, closed flag, date range",
|
|
62
|
+
fields: {
|
|
63
|
+
period_key: { dbDatatype: "varchar", fieldTypeCd: "text", flags: "VEM", isPk: true, isNullable: false, maxLen: 20, orderNum: 1, description: "Period Key" },
|
|
64
|
+
description: { dbDatatype: "varchar", fieldTypeCd: "text", flags: "VEM", maxLen: 100, orderNum: 30, description: "Description" },
|
|
65
|
+
closed: { dbDatatype: "bool", fieldTypeCd: "checkbox", flags: "VEM", isNullable: false, formula: "false", orderNum: 40, description: "Closed" },
|
|
66
|
+
start_date: { dbDatatype: "date", fieldTypeCd: "date", flags: "VEM", orderNum: 50, description: "Start Date" },
|
|
67
|
+
end_date: { dbDatatype: "date", fieldTypeCd: "date", flags: "VEM", orderNum: 60, description: "End Date" },
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
] as const;
|
|
71
|
+
|
|
72
|
+
const byCd = new Map(traits.map((t) => [t.cd, t]));
|
|
73
|
+
|
|
74
|
+
/** Look up a trait by code. */
|
|
75
|
+
export function getTrait(cd: string): TraitDef | undefined {
|
|
76
|
+
return byCd.get(cd);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Title-case a snake_case entity code for the `{Entity}` template token. */
|
|
80
|
+
function titleCaseEntity(entity: string): string {
|
|
81
|
+
const local = entity.split(".").pop() ?? entity;
|
|
82
|
+
return local
|
|
83
|
+
.split(/[_\s]+/)
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
86
|
+
.join(" ");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function applyTemplate(value: string, entity: string): string {
|
|
90
|
+
const local = entity.split(".").pop() ?? entity;
|
|
91
|
+
return value.replace(/\{entity\}/g, local).replace(/\{Entity\}/g, titleCaseEntity(entity));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function templateFields(fields: Record<string, FieldDef>, entity: string): Record<string, FieldDef> {
|
|
95
|
+
const out: Record<string, FieldDef> = {};
|
|
96
|
+
for (const [name, def] of Object.entries(fields)) {
|
|
97
|
+
const key = applyTemplate(name, entity);
|
|
98
|
+
const next: FieldDef = { ...def };
|
|
99
|
+
if (typeof next.description === "string") next.description = applyTemplate(next.description, entity);
|
|
100
|
+
out[key] = next;
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Expand a trait (and any traits it includes) into the concrete fields it adds
|
|
107
|
+
* for `entityName`, with `{entity}` / `{Entity}` tokens resolved. Returns an
|
|
108
|
+
* empty object for unknown or marker traits. Field order follows include-depth
|
|
109
|
+
* first, then declaration order; later definitions win on key collisions.
|
|
110
|
+
*/
|
|
111
|
+
export function expandTrait(traitCd: string, entityName: string): Record<string, FieldDef> {
|
|
112
|
+
const trait = byCd.get(traitCd);
|
|
113
|
+
if (!trait) return {};
|
|
114
|
+
const result: Record<string, FieldDef> = {};
|
|
115
|
+
for (const included of trait.includes ?? []) {
|
|
116
|
+
Object.assign(result, expandTrait(included, entityName));
|
|
117
|
+
}
|
|
118
|
+
Object.assign(result, templateFields(trait.fields, entityName));
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Expand several traits in order into one merged field map. */
|
|
123
|
+
export function expandTraits(traitCds: readonly string[], entityName: string): Record<string, FieldDef> {
|
|
124
|
+
const result: Record<string, FieldDef> = {};
|
|
125
|
+
for (const cd of traitCds) Object.assign(result, expandTrait(cd, entityName));
|
|
126
|
+
return result;
|
|
127
|
+
}
|
package/src/triggers.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Triggers — authoring shape of `logic/triggers.json`. Mirror of triggers.schema.json.
|
|
2
|
+
|
|
3
|
+
/** DB event a trigger or webhook watches. */
|
|
4
|
+
export type EntityEvent = "insert" | "update" | "delete" | "status_change" | "any";
|
|
5
|
+
|
|
6
|
+
/** A single trigger declaration. */
|
|
7
|
+
export interface TriggerDef {
|
|
8
|
+
/** Trigger code, unique within the module. */
|
|
9
|
+
code: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Entity whose events this watches (cross-module via 'module.entity'). */
|
|
12
|
+
entity: string;
|
|
13
|
+
event: EntityEvent;
|
|
14
|
+
/** Optional `[field]`-syntax formula; trigger fires only when true. */
|
|
15
|
+
condition?: string;
|
|
16
|
+
/** Action code to invoke (cross-module form 'module.action' supported). */
|
|
17
|
+
action: string;
|
|
18
|
+
/** Static parameters passed to the action, merged with the injected record id. */
|
|
19
|
+
params?: Record<string, unknown>;
|
|
20
|
+
/** Run the action in the background after the triggering tx commits (default false). */
|
|
21
|
+
async?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** A `logic/triggers.json` file. */
|
|
25
|
+
export interface TriggersFile {
|
|
26
|
+
triggers: TriggerDef[];
|
|
27
|
+
}
|