@atlashub/smartstack-cli 4.45.0 → 4.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
| `entities.json` | Entity definitions | `entities[]` | — |
|
|
17
17
|
| `rules.json` | Business rules | `rules[]` | `businessRules[]` |
|
|
18
18
|
| `usecases.json` | Use cases | `useCases[]` | `usecases[]` (lowercase) |
|
|
19
|
-
| `permissions.json` | Roles and permission matrix | `permissionPaths[]` | `permissionSet.permissions[]`, `
|
|
20
|
-
| `screens.json` | UI screen specifications | `screens[]` | `sections[].resources[]` |
|
|
19
|
+
| `permissions.json` | Roles and permission matrix | `permissionPaths[]` | `permissionSet.permissions[]`, `basePermissions[]`, `actions[]`, `permissions[]` |
|
|
20
|
+
| `screens.json` | UI screen specifications | `screens[]` | `sections[].resources[]`, `sections[]`, `wireframes[]` |
|
|
21
21
|
|
|
22
22
|
The validation script **assembles** these files before checking.
|
|
23
23
|
|
|
@@ -66,17 +66,30 @@ const fs = require('fs');
|
|
|
66
66
|
const path = require('path');
|
|
67
67
|
const dir = process.argv[1];
|
|
68
68
|
|
|
69
|
-
// Load index.json
|
|
70
|
-
|
|
69
|
+
// Load index.json (optional — may not exist at module level)
|
|
70
|
+
let index = {};
|
|
71
|
+
const indexPath = path.join(dir, 'index.json');
|
|
72
|
+
if (fs.existsSync(indexPath)) {
|
|
73
|
+
index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
|
|
74
|
+
}
|
|
71
75
|
const files = index.files || {};
|
|
72
76
|
|
|
73
|
-
// Load flat files
|
|
77
|
+
// Load flat files: try index.json refs first, fallback to direct file load
|
|
74
78
|
function loadFile(key) {
|
|
79
|
+
// Strategy 1: resolve via index.json > files references
|
|
75
80
|
const ref = files[key];
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
if (ref && ref.path) {
|
|
82
|
+
const filePath = path.join(dir, ref.path);
|
|
83
|
+
if (fs.existsSync(filePath)) {
|
|
84
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Strategy 2: direct file load (module dirs without index.json)
|
|
88
|
+
const directPath = path.join(dir, key + '.json');
|
|
89
|
+
if (fs.existsSync(directPath)) {
|
|
90
|
+
return JSON.parse(fs.readFileSync(directPath, 'utf-8'));
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
const entitiesData = loadFile('entities') || {};
|
|
@@ -91,19 +104,40 @@ const hasReferencedEntities = (entitiesData.referencedEntities || []).length > 0
|
|
|
91
104
|
const useCases = usecasesData.useCases || usecasesData.usecases || [];
|
|
92
105
|
const rules = rulesData.rules || rulesData.businessRules || [];
|
|
93
106
|
|
|
94
|
-
// Permissions:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
// Permissions: try all known variants, extract into flat array
|
|
108
|
+
function extractPermissions(data) {
|
|
109
|
+
if (data.permissionPaths && data.permissionPaths.length > 0) return data.permissionPaths;
|
|
110
|
+
if (data.permissionSet && data.permissionSet.permissions && data.permissionSet.permissions.length > 0) {
|
|
111
|
+
return data.permissionSet.permissions.map(function(p) { return p.code || p.path || ''; });
|
|
112
|
+
}
|
|
113
|
+
if (data.basePermissions && data.basePermissions.length > 0) {
|
|
114
|
+
return data.basePermissions.map(function(p) { return p.code || p.path || ''; });
|
|
115
|
+
}
|
|
116
|
+
if (data.actions && data.actions.length > 0) {
|
|
117
|
+
return data.actions.map(function(a) { return a.code || ''; });
|
|
118
|
+
}
|
|
119
|
+
if (data.permissions && data.permissions.length > 0) {
|
|
120
|
+
return data.permissions.map(function(p) { return typeof p === 'string' ? p : (p.code || p.path || ''); });
|
|
121
|
+
}
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
const permissions = extractPermissions(permissionsData);
|
|
125
|
+
|
|
126
|
+
// Screens: canonical screens[] OR sections[] (with or without .resources sub-array)
|
|
127
|
+
function extractScreens(data) {
|
|
128
|
+
if (data.screens && data.screens.length > 0) return data.screens;
|
|
129
|
+
if (data.sections && data.sections.length > 0) {
|
|
130
|
+
// sections may contain resources[] or be screens themselves
|
|
131
|
+
var fromResources = data.sections.reduce(function(acc, s) { return acc.concat(s.resources || []); }, []);
|
|
132
|
+
return fromResources.length > 0 ? fromResources : data.sections;
|
|
133
|
+
}
|
|
134
|
+
if (data.wireframes && data.wireframes.length > 0) return data.wireframes;
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
const allScreens = extractScreens(screensData);
|
|
105
138
|
|
|
106
|
-
|
|
139
|
+
// Status: from index.json if present, or 'specified' if module has thematic files but no index.json
|
|
140
|
+
const status = (index.metadata && index.metadata.status) || (Object.keys(index).length === 0 ? 'specified' : 'unknown');
|
|
107
141
|
|
|
108
142
|
const fails = [];
|
|
109
143
|
|
|
@@ -71,32 +71,27 @@ FOR each module:
|
|
|
71
71
|
|
|
72
72
|
### 4. Load Flat Files Per Module
|
|
73
73
|
|
|
74
|
-
For each module, load the separate JSON files
|
|
74
|
+
For each module, load the separate JSON files directly (index.json may not exist at module level):
|
|
75
75
|
|
|
76
76
|
```javascript
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
const
|
|
83
|
-
const permissionsData = READ(moduleDir + '/permissions.json');
|
|
84
|
-
const screensData = READ(moduleDir + '/screens.json');
|
|
77
|
+
// Load thematic files directly from module directory
|
|
78
|
+
const entitiesData = READ(moduleDir + '/entities.json') || {};
|
|
79
|
+
const usecasesData = READ(moduleDir + '/usecases.json') || {};
|
|
80
|
+
const rulesData = READ(moduleDir + '/rules.json') || {};
|
|
81
|
+
const permissionsData = READ(moduleDir + '/permissions.json') || {};
|
|
82
|
+
const screensData = READ(moduleDir + '/screens.json') || {};
|
|
85
83
|
|
|
86
84
|
// NORMALISATION: tolerate ba-writer + LLM field name variants
|
|
85
|
+
// See acceptance-criteria.md for the full extraction functions
|
|
87
86
|
const moduleData = {
|
|
88
|
-
index: READ(moduleDir + '/index.json'),
|
|
89
87
|
entities: entitiesData.entities || [],
|
|
90
88
|
hasReferencedEntities: (entitiesData.referencedEntities || []).length > 0,
|
|
91
89
|
useCases: usecasesData.useCases || usecasesData.usecases || [],
|
|
92
90
|
rules: rulesData.rules || rulesData.businessRules || [],
|
|
93
|
-
permissions: permissionsData
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
screens: (screensData.screens || []).length > 0
|
|
98
|
-
? screensData.screens
|
|
99
|
-
: (screensData.sections || []).flatMap(s => s.resources || [])
|
|
91
|
+
permissions: extractPermissions(permissionsData),
|
|
92
|
+
// tries: permissionPaths > permissionSet.permissions > basePermissions > actions > permissions
|
|
93
|
+
screens: extractScreens(screensData),
|
|
94
|
+
// tries: screens > sections[].resources > sections > wireframes
|
|
100
95
|
};
|
|
101
96
|
```
|
|
102
97
|
|