@dforge-core/dforge-mcp 0.1.0-rc.1 → 0.1.0-rc.11

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.
@@ -38,7 +38,8 @@
38
38
  "description": "Data sources providing data for this view"
39
39
  },
40
40
  "filter": {
41
- "description": "Default filter criteria"
41
+ "$ref": "#/$defs/filter",
42
+ "description": "Default filter criteria (applied to all dataSources unless one declares its own)"
42
43
  },
43
44
  "order": {
44
45
  "description": "Default sort order"
@@ -291,6 +292,56 @@
291
292
  "parentSetField": {
292
293
  "type": "string",
293
294
  "description": "Set field name on parent entity linking to this detail level"
295
+ },
296
+ "filter": {
297
+ "$ref": "#/$defs/filter",
298
+ "description": "Per-source filter criteria; overrides the view-level filter for this source"
299
+ },
300
+ "order": {
301
+ "description": "Per-source sort order (array of {c, d} entries, where d is 'asc' or 'desc')"
302
+ }
303
+ },
304
+ "additionalProperties": false
305
+ },
306
+
307
+ "filter": {
308
+ "description": "Canonical dForge filter expression. Either a single condition `{c, o, v}` or a group `{g, i: [...]}`. Used by data views, reports, folders (row-level security), and the API.",
309
+ "oneOf": [
310
+ { "$ref": "#/$defs/filterCondition" },
311
+ { "$ref": "#/$defs/filterGroup" }
312
+ ]
313
+ },
314
+ "filterCondition": {
315
+ "type": "object",
316
+ "required": ["c", "o"],
317
+ "properties": {
318
+ "c": {
319
+ "type": "string",
320
+ "description": "Column code (supports dot navigation: 'customer.name')"
321
+ },
322
+ "o": {
323
+ "type": "string",
324
+ "description": "Operator: eq, neq, =, !=, gt, gtEq, grEq, lt, ltEq, in, nIn, like, isNull, isNotNull, etc."
325
+ },
326
+ "v": {
327
+ "description": "Comparison value. Scalars, arrays (for in/nIn), or parameter references like '@param_code'."
328
+ }
329
+ },
330
+ "additionalProperties": false
331
+ },
332
+ "filterGroup": {
333
+ "type": "object",
334
+ "required": ["g", "i"],
335
+ "properties": {
336
+ "g": {
337
+ "type": "string",
338
+ "enum": ["and", "or"],
339
+ "description": "Group combinator"
340
+ },
341
+ "i": {
342
+ "type": "array",
343
+ "items": { "$ref": "#/$defs/filter" },
344
+ "description": "Group items: nested conditions or sub-groups"
294
345
  }
295
346
  },
296
347
  "additionalProperties": false
@@ -33,8 +33,7 @@
33
33
  "description": "SQL SELECT statement for view-backed entities (isView=true). Executed as CREATE OR REPLACE VIEW during module install."
34
34
  },
35
35
  "toString": {
36
- "type": "string",
37
- "description": "Display pattern using column placeholders, e.g. \"{first_name} {last_name}\""
36
+ "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."
38
37
  },
39
38
  "traits": {
40
39
  "type": "array",
@@ -0,0 +1,108 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://dforge.dev/schemas/folders.schema.json",
4
+ "title": "dForge Folders",
5
+ "description": "Folder tree for a dForge module. The file IS the root folder (not a map keyed by code). Sub-folders live under `children`, keyed by folder code.",
6
+ "$ref": "#/$defs/folder",
7
+ "$defs": {
8
+ "folder": {
9
+ "type": "object",
10
+ "properties": {
11
+ "label": {
12
+ "type": "string",
13
+ "description": "Folder display name"
14
+ },
15
+ "description": {
16
+ "type": "string",
17
+ "description": "Optional description text (shown in breadcrumb / header area)"
18
+ },
19
+ "parentCode": {
20
+ "type": ["string", "null"],
21
+ "description": "Parent folder code. Usually omitted: nested folders go under `children` of their parent. Only used by sparse-tree imports."
22
+ },
23
+ "folderPath": {
24
+ "type": "string",
25
+ "description": "URL-friendly folder path override"
26
+ },
27
+ "color": {
28
+ "type": "string",
29
+ "description": "Folder accent color (hex, e.g. '#2196F3')"
30
+ },
31
+ "icon": {
32
+ "type": "string",
33
+ "description": "Bootstrap icon class (e.g. 'bi-folder')"
34
+ },
35
+ "inheritSecurity": {
36
+ "type": "boolean",
37
+ "description": "Whether to inherit security rights from the parent folder. Default: true."
38
+ },
39
+ "entities": {
40
+ "type": "object",
41
+ "description": "Entity code → folder-entity binding (which view to show, quick-add, row-level filter).",
42
+ "additionalProperties": {
43
+ "$ref": "#/$defs/folderEntity"
44
+ }
45
+ },
46
+ "children": {
47
+ "type": "object",
48
+ "description": "Nested folders keyed by sub-folder code. Recursive — children can have their own children.",
49
+ "additionalProperties": {
50
+ "$ref": "#/$defs/folder"
51
+ }
52
+ }
53
+ },
54
+ "additionalProperties": false
55
+ },
56
+ "folderEntity": {
57
+ "type": "object",
58
+ "properties": {
59
+ "viewName": {
60
+ "type": "string",
61
+ "description": "Entity view name (data view code) to use in this folder. Common values include 'default'."
62
+ },
63
+ "quickAdd": {
64
+ "type": "boolean",
65
+ "description": "Enable the quick-add (+) button for this entity in this folder"
66
+ },
67
+ "rowFilter": {
68
+ "description": "Row-level filter. Either a SQL expression string (e.g. \"is_customer = true\") or a canonical filter object (`{c,o,v}` for one condition, `{g,i:[]}` for a group).",
69
+ "oneOf": [
70
+ { "type": "string" },
71
+ { "$ref": "#/$defs/filter" }
72
+ ]
73
+ }
74
+ },
75
+ "additionalProperties": false
76
+ },
77
+
78
+ "filter": {
79
+ "description": "Canonical dForge filter expression — same shape as in data_views.json. Either `{c, o, v}` or `{g, i: [...]}`.",
80
+ "oneOf": [
81
+ { "$ref": "#/$defs/filterCondition" },
82
+ { "$ref": "#/$defs/filterGroup" }
83
+ ]
84
+ },
85
+ "filterCondition": {
86
+ "type": "object",
87
+ "required": ["c", "o"],
88
+ "properties": {
89
+ "c": { "type": "string" },
90
+ "o": { "type": "string" },
91
+ "v": {}
92
+ },
93
+ "additionalProperties": false
94
+ },
95
+ "filterGroup": {
96
+ "type": "object",
97
+ "required": ["g", "i"],
98
+ "properties": {
99
+ "g": { "type": "string", "enum": ["and", "or"] },
100
+ "i": {
101
+ "type": "array",
102
+ "items": { "$ref": "#/$defs/filter" }
103
+ }
104
+ },
105
+ "additionalProperties": false
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "dForge Module Scheduled Jobs",
4
+ "description": "Cron job declarations for a dForge module package (logic/jobs.json). The dForge.Scheduler service polls these and fires each job on its schedule.",
5
+ "type": "object",
6
+ "required": ["jobs"],
7
+ "properties": {
8
+ "jobs": {
9
+ "type": "array",
10
+ "maxItems": 50,
11
+ "description": "At most 50 jobs per module — guard against accidental fan-out from generated declarations.",
12
+ "items": {
13
+ "type": "object",
14
+ "required": ["code", "action", "schedule", "timeout"],
15
+ "properties": {
16
+ "code": {
17
+ "type": "string",
18
+ "maxLength": 100,
19
+ "pattern": "^[a-z][a-z0-9_]*$",
20
+ "description": "Unique identifier within the module."
21
+ },
22
+ "description": {
23
+ "type": "string",
24
+ "description": "Human-readable description of what the job does."
25
+ },
26
+ "action": {
27
+ "type": "string",
28
+ "description": "Action code in this module (e.g. 'generate_invoices'). The scheduler resolves it to action_implementation.impl_id at install time."
29
+ },
30
+ "schedule": {
31
+ "type": "string",
32
+ "description": "Five-field cron expression (minute granularity). Sub-minute schedules are rejected.",
33
+ "pattern": "^\\S+\\s+\\S+\\s+\\S+\\s+\\S+\\s+\\S+$"
34
+ },
35
+ "params": {
36
+ "type": "object",
37
+ "description": "Static parameters passed to the action as __params. Folder-scoped overrides go through module settings, not here.",
38
+ "additionalProperties": true
39
+ },
40
+ "timeout": {
41
+ "type": "integer",
42
+ "minimum": 1,
43
+ "maximum": 3600,
44
+ "description": "Hard timeout in seconds. Required — there is no implicit default. Must be > 300 only if class = 'long_running' (60-minute hard ceiling)."
45
+ },
46
+ "concurrency": {
47
+ "type": "integer",
48
+ "minimum": 1,
49
+ "maximum": 5,
50
+ "default": 1,
51
+ "description": "Max parallel runs. 1 means single-instance; the scheduler skips a new fire if a previous one is still in flight (Phase 3 enforcement)."
52
+ },
53
+ "idempotencyKey": {
54
+ "type": "string",
55
+ "description": "Template like '{job_cd}:{run.month}'. Resolved at fire time. A successful run with the same key blocks re-dispatch (Phase 3 enforcement)."
56
+ },
57
+ "class": {
58
+ "type": "string",
59
+ "enum": ["standard", "long_running"],
60
+ "default": "standard",
61
+ "description": "Routing class. 'long_running' is opt-in and required for any timeout > 300 seconds."
62
+ },
63
+ "timeZone": {
64
+ "type": "string",
65
+ "description": "IANA tz name (e.g. 'Asia/Tokyo'). Overrides the tenant default. Omit to fall back to auth.tenant.time_zone."
66
+ },
67
+ "enabled": {
68
+ "type": "boolean",
69
+ "default": true,
70
+ "description": "Master switch. False fully disables (no scheduler, no manual trigger)."
71
+ },
72
+ "paused": {
73
+ "type": "boolean",
74
+ "default": false,
75
+ "description": "Soft pause. Scheduler skips firing, but admin 'trigger now' still works."
76
+ }
77
+ },
78
+ "additionalProperties": false
79
+ }
80
+ }
81
+ },
82
+ "additionalProperties": false
83
+ }
@@ -21,6 +21,12 @@
21
21
  "pattern": "^[a-z][a-z0-9_-]*$",
22
22
  "description": "Human-readable module code (becomes schema name and module_cd in DB)"
23
23
  },
24
+ "kind": {
25
+ "type": "string",
26
+ "enum": ["module", "pack"],
27
+ "default": "module",
28
+ "description": "Package kind. 'module' (default) — a regular module with its own entities/views/actions. 'pack' — a dependency bundle: installs a curated set of other modules via `dependencies` in order, owns no entities itself."
29
+ },
24
30
  "version": {
25
31
  "type": "string",
26
32
  "pattern": "^\\d+\\.\\d+\\.\\d+",
@@ -68,12 +74,37 @@
68
74
  },
69
75
  "dependencies": {
70
76
  "type": "object",
71
- "description": "Module dependencies: module code → semver range",
77
+ "description": "Module dependencies: module code → semver range OR { version, entities? } object for partial deps that only import specific entities from the dependency.",
72
78
  "additionalProperties": {
73
- "type": "string",
74
- "description": "Semver version range (e.g. '>=1.0.0')"
79
+ "oneOf": [
80
+ {
81
+ "type": "string",
82
+ "description": "Semver version range (e.g. '>=1.0.0')"
83
+ },
84
+ {
85
+ "type": "object",
86
+ "required": ["version"],
87
+ "properties": {
88
+ "version": {
89
+ "type": "string",
90
+ "description": "Semver version range"
91
+ },
92
+ "entities": {
93
+ "type": "array",
94
+ "items": { "type": "string" },
95
+ "description": "Entity codes from the dependency that this module needs. If omitted, all entities are accessible."
96
+ }
97
+ },
98
+ "additionalProperties": false
99
+ }
100
+ ]
75
101
  }
76
102
  },
103
+ "auditHistory": {
104
+ "type": "string",
105
+ "enum": ["none", "minimal", "full"],
106
+ "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."
107
+ },
77
108
  "entities": {
78
109
  "type": "object",
79
110
  "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).",
@@ -86,6 +117,11 @@
86
117
  "type": "string",
87
118
  "description": "Module category for display (e.g. 'Integration', 'Finance')"
88
119
  },
120
+ "tags": {
121
+ "type": "array",
122
+ "items": { "type": "string" },
123
+ "description": "Free-form tags for search and discovery (e.g. ['crm', 'sales', 'leads']). Convention: lowercase, hyphen-separated."
124
+ },
89
125
  "icon": {
90
126
  "type": "string",
91
127
  "description": "Bootstrap icon class (e.g. 'bi-link-45deg')"
@@ -94,6 +130,16 @@
94
130
  "type": "array",
95
131
  "items": { "type": "string", "pattern": "^[a-z]{2,3}(-[A-Z]{2})?$" },
96
132
  "description": "Non-English locales the package promises to translate. Each entry MUST match a translations/<locale>.json file, and every translatable resource (entity/field labels, folders, views, menus + items, actions + params, reports + datasets + params, settings) MUST have a label in that file. English is the default — don't list 'en' or 'en-US'."
133
+ },
134
+ "created": {
135
+ "type": "string",
136
+ "format": "date",
137
+ "description": "Initial creation date of the module package (YYYY-MM-DD). Informational only; not enforced by the installer."
138
+ },
139
+ "updated": {
140
+ "type": "string",
141
+ "format": "date",
142
+ "description": "Last edit date of the manifest (YYYY-MM-DD). Informational; bump when shipping a new version."
97
143
  }
98
144
  },
99
145
  "additionalProperties": false
@@ -0,0 +1,86 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://dforge.dev/schemas/menus.schema.json",
4
+ "title": "dForge Menus",
5
+ "description": "Menu definitions for a dForge module",
6
+ "type": "object",
7
+ "additionalProperties": {
8
+ "$ref": "#/$defs/menu"
9
+ },
10
+ "$defs": {
11
+ "menu": {
12
+ "type": "object",
13
+ "required": ["label", "items"],
14
+ "properties": {
15
+ "label": {
16
+ "type": "string",
17
+ "description": "Menu display name"
18
+ },
19
+ "description": {
20
+ "type": "string",
21
+ "description": "Optional description text (tooltip, subtitle)"
22
+ },
23
+ "folders": {
24
+ "type": "array",
25
+ "items": { "type": "string" },
26
+ "description": "Folder codes where this menu is available"
27
+ },
28
+ "items": {
29
+ "type": "object",
30
+ "description": "Menu items keyed by item code",
31
+ "additionalProperties": {
32
+ "$ref": "#/$defs/menuItem"
33
+ }
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ },
38
+ "menuItem": {
39
+ "type": "object",
40
+ "required": ["label"],
41
+ "properties": {
42
+ "itemType": {
43
+ "type": ["string", "null"],
44
+ "enum": ["V", "D", "R", null],
45
+ "description": "Item type: V=Data View, D=Document, R=Report, null=folder/section"
46
+ },
47
+ "dataViewCode": {
48
+ "type": "string",
49
+ "description": "Data view code (when itemType is 'V')"
50
+ },
51
+ "documentCode": {
52
+ "type": "string",
53
+ "description": "Document code (when itemType is 'D')"
54
+ },
55
+ "reportCode": {
56
+ "type": "string",
57
+ "description": "Report code (when itemType is 'R')"
58
+ },
59
+ "orderNum": {
60
+ "type": "integer",
61
+ "description": "Display order"
62
+ },
63
+ "label": {
64
+ "type": "string",
65
+ "description": "Menu item display text"
66
+ },
67
+ "description": {
68
+ "type": "string",
69
+ "description": "Optional description text (tooltip, subtitle)"
70
+ },
71
+ "icon": {
72
+ "type": "string",
73
+ "description": "Bootstrap icon name"
74
+ },
75
+ "children": {
76
+ "type": "object",
77
+ "description": "Child menu items (for folder/section items)",
78
+ "additionalProperties": {
79
+ "$ref": "#/$defs/menuItem"
80
+ }
81
+ }
82
+ },
83
+ "additionalProperties": false
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,82 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "dForge Module Print Templates",
4
+ "description": "Print template declarations for a dForge module package (ui/print_templates.json). Each key is the template_cd; the value declares either a printable template (default) or a reusable snippet pulled into other templates via {% include 'module_cd.snippet_cd' %}.",
5
+ "type": "object",
6
+ "additionalProperties": {
7
+ "type": "object",
8
+ "properties": {
9
+ "type": {
10
+ "type": "string",
11
+ "enum": ["template", "snippet"],
12
+ "default": "template",
13
+ "description": "'template' (default) — a full printable form bound to an entity. 'snippet' — a reusable Liquid partial, module-scoped, no entity binding, included from other templates."
14
+ },
15
+ "entityCd": {
16
+ "type": "string",
17
+ "description": "Entity code this template renders. Required when type='template'; ignored when type='snippet'. Cross-module form 'module.entity' is supported (e.g. fin-ch ships a template for fin.invoice)."
18
+ },
19
+ "description": {
20
+ "type": "string",
21
+ "description": "Human-readable label shown in the print menu."
22
+ },
23
+ "template": {
24
+ "type": "string",
25
+ "description": "Inline Liquid HTML. Either 'template' or 'file' must be set; 'file' takes precedence when both are present."
26
+ },
27
+ "file": {
28
+ "type": "string",
29
+ "description": "Relative path under the module's print_templates/ directory (e.g. 'invoice.html'). Loaded at install time."
30
+ },
31
+ "css": {
32
+ "type": "string",
33
+ "description": "Inline CSS, or a filename ending in .css (resolved relative to print_templates/). Snippets typically inherit CSS from the host template and omit this."
34
+ },
35
+ "pageSettings": {
36
+ "type": "object",
37
+ "description": "Default page geometry applied when the user prints from the UI. Stored as jsonb on the row; the editor lets users tweak per-template.",
38
+ "properties": {
39
+ "size": {
40
+ "type": "string",
41
+ "enum": ["A4", "letter", "legal"],
42
+ "default": "A4"
43
+ },
44
+ "orientation": {
45
+ "type": "string",
46
+ "enum": ["portrait", "landscape"],
47
+ "default": "portrait"
48
+ },
49
+ "margins": {
50
+ "type": "object",
51
+ "properties": {
52
+ "top": { "type": "string", "description": "CSS length, e.g. '15mm'." },
53
+ "right": { "type": "string" },
54
+ "bottom": { "type": "string" },
55
+ "left": { "type": "string" }
56
+ },
57
+ "additionalProperties": false
58
+ }
59
+ },
60
+ "additionalProperties": false
61
+ }
62
+ },
63
+ "additionalProperties": false,
64
+ "allOf": [
65
+ {
66
+ "if": { "properties": { "type": { "const": "snippet" } }, "required": ["type"] },
67
+ "then": {
68
+ "description": "Snippets must not declare entityCd and their template_cd must not contain '.' (collides with {% include 'module_cd.snippet_cd' %})."
69
+ },
70
+ "else": {
71
+ "required": ["entityCd"]
72
+ }
73
+ },
74
+ {
75
+ "anyOf": [
76
+ { "required": ["file"] },
77
+ { "required": ["template"] }
78
+ ]
79
+ }
80
+ ]
81
+ }
82
+ }