@dimescheduler/setup 0.1.1 → 0.1.3
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/README.md +8 -8
- package/dist/bundle-5KNZSFFQ.js +10 -0
- package/dist/chunk-VHT6HO3N.js +863 -0
- package/dist/index.js +205 -448
- package/package.json +13 -8
package/dist/index.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
compileLayoutsDocument,
|
|
4
|
+
compileProfileDocument,
|
|
5
|
+
compileUsersDocument,
|
|
6
|
+
detectDocumentType,
|
|
7
|
+
isBundleDocument,
|
|
8
|
+
isDocumentReference,
|
|
9
|
+
isLayoutsDocument,
|
|
10
|
+
isProfileDocument,
|
|
11
|
+
isUsersDocument
|
|
12
|
+
} from "./chunk-VHT6HO3N.js";
|
|
2
13
|
|
|
3
14
|
// src/index.ts
|
|
4
15
|
import { Command as Command4 } from "commander";
|
|
@@ -34,452 +45,177 @@ function hasComponent(nodes, componentType) {
|
|
|
34
45
|
}
|
|
35
46
|
return false;
|
|
36
47
|
}
|
|
37
|
-
function
|
|
48
|
+
function validateProfileSettings(settings, prefix = "") {
|
|
38
49
|
const issues = [];
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
const p = prefix ? `${prefix}: ` : "";
|
|
51
|
+
if (!settings.name?.trim()) {
|
|
52
|
+
issues.push({ type: "error", message: `${p}Profile name is required` });
|
|
41
53
|
}
|
|
42
|
-
if (!
|
|
43
|
-
issues.push({ type: "error", message:
|
|
54
|
+
if (!settings.code?.trim()) {
|
|
55
|
+
issues.push({ type: "error", message: `${p}Profile code is required` });
|
|
44
56
|
}
|
|
45
|
-
if (!
|
|
46
|
-
issues.push({ type: "error", message:
|
|
57
|
+
if (!settings.workspace || settings.workspace.length === 0) {
|
|
58
|
+
issues.push({ type: "error", message: `${p}Workspace must have at least one element` });
|
|
47
59
|
} else {
|
|
48
|
-
const componentCount = countComponents(
|
|
60
|
+
const componentCount = countComponents(settings.workspace);
|
|
49
61
|
if (componentCount === 0) {
|
|
50
|
-
issues.push({ type: "warning", message:
|
|
62
|
+
issues.push({ type: "warning", message: `${p}Workspace has no components` });
|
|
51
63
|
}
|
|
52
|
-
const hasPlanningBoard = hasComponent(
|
|
64
|
+
const hasPlanningBoard = hasComponent(settings.workspace, "planningBoard");
|
|
53
65
|
if (!hasPlanningBoard) {
|
|
54
|
-
issues.push({ type: "warning", message:
|
|
66
|
+
issues.push({ type: "warning", message: `${p}Consider adding a Planning Board component` });
|
|
55
67
|
}
|
|
56
68
|
}
|
|
57
|
-
|
|
58
|
-
profile.users.forEach((user, index) => {
|
|
59
|
-
if (!user.name?.trim()) {
|
|
60
|
-
issues.push({ type: "error", message: `User ${index + 1}: Name is required` });
|
|
61
|
-
}
|
|
62
|
-
if (!user.email?.trim()) {
|
|
63
|
-
issues.push({ type: "error", message: `User ${index + 1}: Email is required` });
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
const errors = issues.filter((i) => i.type === "error");
|
|
68
|
-
const warnings = issues.filter((i) => i.type === "warning");
|
|
69
|
-
return {
|
|
70
|
-
valid: errors.length === 0,
|
|
71
|
-
errors,
|
|
72
|
-
warnings
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// src/core/compile.ts
|
|
77
|
-
var SNAP_MODE_MAP = {
|
|
78
|
-
"none": 1,
|
|
79
|
-
"off": 1,
|
|
80
|
-
"5min": 2,
|
|
81
|
-
"5minutes": 2,
|
|
82
|
-
"10min": 3,
|
|
83
|
-
"10minutes": 3,
|
|
84
|
-
"15min": 4,
|
|
85
|
-
"15minutes": 4,
|
|
86
|
-
"30min": 5,
|
|
87
|
-
"30minutes": 5,
|
|
88
|
-
"halfhour": 5,
|
|
89
|
-
"1hour": 6,
|
|
90
|
-
"1h": 6,
|
|
91
|
-
"hour": 6,
|
|
92
|
-
"12hours": 7,
|
|
93
|
-
"12h": 7,
|
|
94
|
-
"1day": 8,
|
|
95
|
-
"1d": 8,
|
|
96
|
-
"day": 8,
|
|
97
|
-
"2hours": 9,
|
|
98
|
-
"2h": 9,
|
|
99
|
-
"4hours": 10,
|
|
100
|
-
"4h": 10
|
|
101
|
-
};
|
|
102
|
-
var RANGE_MODE_MAP = {
|
|
103
|
-
"day": 1,
|
|
104
|
-
"days": 1,
|
|
105
|
-
"hours": 1,
|
|
106
|
-
"week": 2,
|
|
107
|
-
"weeks": 2,
|
|
108
|
-
"month": 3,
|
|
109
|
-
"months": 3,
|
|
110
|
-
"custom": 4
|
|
111
|
-
};
|
|
112
|
-
var START_MODE_MAP = {
|
|
113
|
-
"today": 1,
|
|
114
|
-
"absolute": 1,
|
|
115
|
-
"startofweek": 2,
|
|
116
|
-
"relative": 2,
|
|
117
|
-
"startofmonth": 3,
|
|
118
|
-
"todayoffset": 4
|
|
119
|
-
};
|
|
120
|
-
var COMPONENT_TO_GL = {
|
|
121
|
-
"openTasks": "openTasksGridComponent",
|
|
122
|
-
"planningBoard": "schedulerComponent",
|
|
123
|
-
"mapComponent": "mapComponent",
|
|
124
|
-
"indicators": "categoriesComponent",
|
|
125
|
-
"resourceFilters": "filterComponent",
|
|
126
|
-
"plannedTasksGridComponent": "plannedTasksGridComponent",
|
|
127
|
-
"propertygridComponent": "propertygridComponent",
|
|
128
|
-
"datePickerComponent": "datePickerComponent",
|
|
129
|
-
"ganttComponent": "ganttComponent",
|
|
130
|
-
"capacityComponent": "capacityComponent",
|
|
131
|
-
"routeSequenceComponent": "routeSequenceComponent",
|
|
132
|
-
"notificationsComponent": "notificationsComponent"
|
|
133
|
-
};
|
|
134
|
-
var COMPONENT_TO_CONTEXT = {
|
|
135
|
-
"planningBoard": "scheduler",
|
|
136
|
-
"openTasks": "unplannedTasksGrid",
|
|
137
|
-
"plannedTasksGridComponent": "plannedTasksGrid",
|
|
138
|
-
"notificationsComponent": "notificationsGrid",
|
|
139
|
-
"propertygridComponent": "detailsGrid",
|
|
140
|
-
"capacityComponent": "pivotGrid",
|
|
141
|
-
"ganttComponent": "gantt",
|
|
142
|
-
"routeSequenceComponent": "routeSequenceGrid"
|
|
143
|
-
};
|
|
144
|
-
var VIEW_PRESET_MAP = {
|
|
145
|
-
"day": "1",
|
|
146
|
-
"1": "1",
|
|
147
|
-
"week": "2",
|
|
148
|
-
"2": "2",
|
|
149
|
-
"workweek": "3",
|
|
150
|
-
"workWeek": "3",
|
|
151
|
-
"work_week": "3",
|
|
152
|
-
"3": "3",
|
|
153
|
-
"month": "4",
|
|
154
|
-
"4": "4"
|
|
155
|
-
};
|
|
156
|
-
var ROW_HEIGHT_MAP = {
|
|
157
|
-
"1row": 25,
|
|
158
|
-
"1rows": 25,
|
|
159
|
-
"1": 25,
|
|
160
|
-
"25": 25,
|
|
161
|
-
"2rows": 38,
|
|
162
|
-
"2row": 38,
|
|
163
|
-
"2": 38,
|
|
164
|
-
"38": 38,
|
|
165
|
-
"3rows": 50,
|
|
166
|
-
"3row": 50,
|
|
167
|
-
"3": 50,
|
|
168
|
-
"50": 50,
|
|
169
|
-
"4rows": 63,
|
|
170
|
-
"4row": 63,
|
|
171
|
-
"4": 63,
|
|
172
|
-
"63": 63
|
|
173
|
-
};
|
|
174
|
-
function mapSnapMode(mode) {
|
|
175
|
-
if (!mode) return 6;
|
|
176
|
-
return SNAP_MODE_MAP[mode.toLowerCase()] ?? 6;
|
|
177
|
-
}
|
|
178
|
-
function mapRangeMode(mode) {
|
|
179
|
-
if (!mode) return 2;
|
|
180
|
-
return RANGE_MODE_MAP[mode.toLowerCase()] ?? 2;
|
|
69
|
+
return issues;
|
|
181
70
|
}
|
|
182
|
-
function
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const v = unit.toLowerCase();
|
|
189
|
-
if (["km", "kilometer", "kilometers"].includes(v)) return "Kilometers";
|
|
190
|
-
if (["mi", "mile", "miles"].includes(v)) return "Miles";
|
|
191
|
-
return unit;
|
|
192
|
-
}
|
|
193
|
-
function componentToGlName(name) {
|
|
194
|
-
return COMPONENT_TO_GL[name] ?? name;
|
|
195
|
-
}
|
|
196
|
-
function componentToContext(name) {
|
|
197
|
-
return COMPONENT_TO_CONTEXT[name] ?? name.toLowerCase();
|
|
198
|
-
}
|
|
199
|
-
function mapViewPreset(value) {
|
|
200
|
-
if (value === void 0 || value === null) return "2";
|
|
201
|
-
const v = String(value).toLowerCase().replace(/[\s_-]+/g, "");
|
|
202
|
-
return VIEW_PRESET_MAP[v] ?? String(value);
|
|
203
|
-
}
|
|
204
|
-
function mapRowHeight(value) {
|
|
205
|
-
if (value === void 0 || value === null) return 38;
|
|
206
|
-
const v = String(value).toLowerCase().replace(/[\s_-]+/g, "");
|
|
207
|
-
if (ROW_HEIGHT_MAP[v] !== void 0) return ROW_HEIGHT_MAP[v];
|
|
208
|
-
const parsed = parseInt(String(value), 10);
|
|
209
|
-
return isNaN(parsed) ? 38 : parsed;
|
|
210
|
-
}
|
|
211
|
-
function workspaceNodeToGL(node) {
|
|
212
|
-
const gl = { type: node.type };
|
|
213
|
-
if ("width" in node && node.width !== void 0) {
|
|
214
|
-
gl.width = node.width;
|
|
215
|
-
}
|
|
216
|
-
if ("height" in node && node.height !== void 0) {
|
|
217
|
-
gl.height = node.height;
|
|
218
|
-
}
|
|
219
|
-
if (node.type === "row" || node.type === "column" || node.type === "stack") {
|
|
220
|
-
gl.isClosable = true;
|
|
221
|
-
gl.reorderEnabled = true;
|
|
222
|
-
gl.title = "";
|
|
223
|
-
if ("content" in node && node.content) {
|
|
224
|
-
gl.content = node.content.map(workspaceNodeToGL);
|
|
71
|
+
function validateUsers(users, prefix = "") {
|
|
72
|
+
const issues = [];
|
|
73
|
+
const p = prefix ? `${prefix} ` : "";
|
|
74
|
+
users.forEach((user, index) => {
|
|
75
|
+
if (!user.name?.trim()) {
|
|
76
|
+
issues.push({ type: "error", message: `${p}User ${index + 1}: Name is required` });
|
|
225
77
|
}
|
|
226
|
-
if (
|
|
227
|
-
|
|
78
|
+
if (!user.email?.trim()) {
|
|
79
|
+
issues.push({ type: "error", message: `${p}User ${index + 1}: Email is required` });
|
|
228
80
|
}
|
|
229
|
-
|
|
81
|
+
});
|
|
82
|
+
return issues;
|
|
83
|
+
}
|
|
84
|
+
function validateProfile(doc) {
|
|
85
|
+
const issues = [];
|
|
86
|
+
if (!doc || typeof doc !== "object") {
|
|
87
|
+
issues.push({ type: "error", message: "Invalid document: expected an object" });
|
|
88
|
+
return { valid: false, errors: issues, warnings: [] };
|
|
230
89
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
90
|
+
const obj = doc;
|
|
91
|
+
const docType = obj.type;
|
|
92
|
+
switch (docType) {
|
|
93
|
+
case "profile": {
|
|
94
|
+
if (!obj.payload || typeof obj.payload !== "object") {
|
|
95
|
+
issues.push({ type: "error", message: 'Profile document must have a "payload" property' });
|
|
96
|
+
} else {
|
|
97
|
+
issues.push(...validateProfileSettings(obj.payload));
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
235
100
|
}
|
|
236
|
-
|
|
237
|
-
|
|
101
|
+
case "users": {
|
|
102
|
+
if (!Array.isArray(obj.payload)) {
|
|
103
|
+
issues.push({ type: "error", message: 'Users document must have a "payload" array' });
|
|
104
|
+
} else {
|
|
105
|
+
issues.push(...validateUsers(obj.payload));
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
238
108
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
gl.id = compId;
|
|
245
|
-
compState.id = compId;
|
|
246
|
-
} else if (compName === "schedulerComponent") {
|
|
247
|
-
gl.id = "schedulerContainer";
|
|
248
|
-
compState.id = "scheduler";
|
|
109
|
+
case "layouts": {
|
|
110
|
+
if (!Array.isArray(obj.payload)) {
|
|
111
|
+
issues.push({ type: "error", message: 'Layouts document must have a "payload" array' });
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
249
114
|
}
|
|
250
|
-
|
|
251
|
-
|
|
115
|
+
case "bundle": {
|
|
116
|
+
if (!obj.name?.toString().trim()) {
|
|
117
|
+
issues.push({ type: "error", message: "Bundle name is required" });
|
|
118
|
+
}
|
|
119
|
+
if (!Array.isArray(obj.documents)) {
|
|
120
|
+
issues.push({ type: "error", message: 'Bundle must have a "documents" array' });
|
|
121
|
+
} else {
|
|
122
|
+
const documents = obj.documents;
|
|
123
|
+
let profileCount = 0;
|
|
124
|
+
documents.forEach((item, index) => {
|
|
125
|
+
if ("$ref" in item) {
|
|
126
|
+
if (typeof item.$ref !== "string") {
|
|
127
|
+
issues.push({ type: "error", message: `Document ${index + 1}: $ref must be a string` });
|
|
128
|
+
}
|
|
129
|
+
} else if (item.type === "profile") {
|
|
130
|
+
profileCount++;
|
|
131
|
+
if (item.payload && typeof item.payload === "object") {
|
|
132
|
+
const profileName = item.payload.name || `Profile ${profileCount}`;
|
|
133
|
+
issues.push(...validateProfileSettings(item.payload, profileName));
|
|
134
|
+
} else {
|
|
135
|
+
issues.push({ type: "error", message: `Document ${index + 1}: Profile must have a "payload" property` });
|
|
136
|
+
}
|
|
137
|
+
} else if (item.type === "users") {
|
|
138
|
+
if (Array.isArray(item.payload)) {
|
|
139
|
+
issues.push(...validateUsers(item.payload));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
if (profileCount === 0) {
|
|
144
|
+
issues.push({ type: "warning", message: "Bundle contains no profile documents" });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
252
148
|
}
|
|
253
|
-
|
|
254
|
-
|
|
149
|
+
default: {
|
|
150
|
+
issues.push(...validateProfileSettings({
|
|
151
|
+
name: obj.name,
|
|
152
|
+
code: obj.code,
|
|
153
|
+
workspace: obj.workspace
|
|
154
|
+
}));
|
|
155
|
+
if (Array.isArray(obj.users)) {
|
|
156
|
+
issues.push(...validateUsers(obj.users));
|
|
157
|
+
}
|
|
255
158
|
}
|
|
256
|
-
return gl;
|
|
257
159
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
function workspaceToGoldenLayout(workspace) {
|
|
160
|
+
const errors = issues.filter((i) => i.type === "error");
|
|
161
|
+
const warnings = issues.filter((i) => i.type === "warning");
|
|
261
162
|
return {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
reorderEnabled: true,
|
|
266
|
-
selectionEnabled: true,
|
|
267
|
-
popoutWholeStack: false,
|
|
268
|
-
blockedPopoutsThrowError: true,
|
|
269
|
-
closePopoutsOnUnload: true,
|
|
270
|
-
showPopoutIcon: false,
|
|
271
|
-
showMaximiseIcon: true,
|
|
272
|
-
showCloseIcon: true,
|
|
273
|
-
responsiveMode: "onload",
|
|
274
|
-
tabOverlapAllowance: 0,
|
|
275
|
-
reorderOnTabMenuClick: true,
|
|
276
|
-
tabControlOffset: 10
|
|
277
|
-
},
|
|
278
|
-
dimensions: {
|
|
279
|
-
borderWidth: 5,
|
|
280
|
-
borderGrabWidth: 15,
|
|
281
|
-
minItemHeight: 10,
|
|
282
|
-
minItemWidth: 10,
|
|
283
|
-
headerHeight: 20,
|
|
284
|
-
dragProxyWidth: 300,
|
|
285
|
-
dragProxyHeight: 200
|
|
286
|
-
},
|
|
287
|
-
labels: {
|
|
288
|
-
close: "Close",
|
|
289
|
-
maximise: "Maximize",
|
|
290
|
-
minimise: "Minimize",
|
|
291
|
-
popout: "open in new window",
|
|
292
|
-
popin: "pop in",
|
|
293
|
-
tabDropdown: "Additional Tabs"
|
|
294
|
-
},
|
|
295
|
-
content: [
|
|
296
|
-
{
|
|
297
|
-
type: "row",
|
|
298
|
-
isClosable: true,
|
|
299
|
-
reorderEnabled: true,
|
|
300
|
-
title: "",
|
|
301
|
-
content: workspace.map(workspaceNodeToGL)
|
|
302
|
-
}
|
|
303
|
-
],
|
|
304
|
-
isClosable: true,
|
|
305
|
-
reorderEnabled: true,
|
|
306
|
-
title: "",
|
|
307
|
-
openPopouts: [],
|
|
308
|
-
maximisedItemId: null
|
|
163
|
+
valid: errors.length === 0,
|
|
164
|
+
errors,
|
|
165
|
+
warnings
|
|
309
166
|
};
|
|
310
167
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
direction: layout.grouper.direction,
|
|
320
|
-
id: layout.grouper.id || layout.grouper.property
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
const filters = (layout.filters || []).map((f) => ({
|
|
324
|
-
operator: f.operator || "like",
|
|
325
|
-
value: f.value || "",
|
|
326
|
-
property: f.property,
|
|
327
|
-
exactMatch: f.exactMatch ?? false
|
|
328
|
-
}));
|
|
329
|
-
const lockedGridWidth = layout.lockedGridWidth || layout.resourcesGridWidth || null;
|
|
330
|
-
const fitToScreen = typeof layout.fitToScreen === "boolean" ? layout.fitToScreen : layout.fitToScreen === "true";
|
|
331
|
-
const ignoreCalendars = typeof layout.ignoreCalendars === "boolean" ? layout.ignoreCalendars : layout.ignoreCalendars === "true";
|
|
332
|
-
const pageSize = layout.pageSize !== void 0 ? typeof layout.pageSize === "number" ? layout.pageSize : parseInt(String(layout.pageSize), 10) : 50;
|
|
333
|
-
const state = {
|
|
334
|
-
columns,
|
|
335
|
-
storeState: grouper ? { grouper } : {},
|
|
336
|
-
filters,
|
|
337
|
-
viewPreset: layout.viewPreset !== void 0 ? mapViewPreset(layout.viewPreset) : null,
|
|
338
|
-
Id: layout.id || gridName,
|
|
339
|
-
lockedGridWidth,
|
|
340
|
-
pageSize: isNaN(pageSize) ? 50 : pageSize,
|
|
341
|
-
fitToScreen,
|
|
342
|
-
rowHeight: mapRowHeight(layout.rowHeight),
|
|
343
|
-
ignoreCalendars
|
|
168
|
+
|
|
169
|
+
// src/core/compile/index.ts
|
|
170
|
+
function compileToApiPayload(doc) {
|
|
171
|
+
const result = {
|
|
172
|
+
profiles: [],
|
|
173
|
+
layouts: [],
|
|
174
|
+
profileLayouts: [],
|
|
175
|
+
users: []
|
|
344
176
|
};
|
|
345
|
-
if (
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
state[field] = layout[field];
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
return state;
|
|
371
|
-
}
|
|
372
|
-
function collectLayouts(nodes) {
|
|
373
|
-
const acc = [];
|
|
374
|
-
for (const node of nodes) {
|
|
375
|
-
if (node.type === "row" || node.type === "column" || node.type === "stack") {
|
|
376
|
-
if ("content" in node && node.content) {
|
|
377
|
-
acc.push(...collectLayouts(node.content));
|
|
177
|
+
if (isProfileDocument(doc)) {
|
|
178
|
+
const compiled = compileProfileDocument(doc);
|
|
179
|
+
result.profiles = compiled.payload.profiles;
|
|
180
|
+
result.layouts = compiled.payload.layouts;
|
|
181
|
+
result.profileLayouts = compiled.payload.profileLayouts;
|
|
182
|
+
result.owner = compiled.payload.owner;
|
|
183
|
+
result.notificationEmail = compiled.payload.notificationEmail;
|
|
184
|
+
} else if (isUsersDocument(doc)) {
|
|
185
|
+
const compiled = compileUsersDocument(doc);
|
|
186
|
+
result.users = compiled.payload.users;
|
|
187
|
+
result.owner = compiled.payload.owner;
|
|
188
|
+
result.notificationEmail = compiled.payload.notificationEmail;
|
|
189
|
+
} else if (isLayoutsDocument(doc)) {
|
|
190
|
+
const compiled = compileLayoutsDocument(doc);
|
|
191
|
+
result.layouts = compiled.payload.layouts;
|
|
192
|
+
result.owner = compiled.payload.owner;
|
|
193
|
+
result.notificationEmail = compiled.payload.notificationEmail;
|
|
194
|
+
} else if (isBundleDocument(doc)) {
|
|
195
|
+
const bundle = doc;
|
|
196
|
+
for (const item of bundle.documents) {
|
|
197
|
+
if (isDocumentReference(item)) {
|
|
198
|
+
throw new Error("Bundle contains $ref items. Use compileToApiPayloadAsync instead.");
|
|
378
199
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const layoutName = layoutItem.name || node.title || gridName;
|
|
391
|
-
let layoutCode = layoutItem.code;
|
|
392
|
-
if (!layoutCode && gridName) {
|
|
393
|
-
layoutCode = gridName.toUpperCase().replace(/-/g, "_");
|
|
394
|
-
}
|
|
395
|
-
acc.push({
|
|
396
|
-
context,
|
|
397
|
-
grid: gridName,
|
|
398
|
-
value: buildLayoutState(layoutItem, gridName),
|
|
399
|
-
name: layoutName,
|
|
400
|
-
code: layoutCode || gridName.toUpperCase(),
|
|
401
|
-
componentId: gridName,
|
|
402
|
-
default: layoutItem.default ?? false,
|
|
403
|
-
public: layoutItem.shared?.public ?? false,
|
|
404
|
-
userGroup: layoutItem.shared?.userGroup
|
|
405
|
-
});
|
|
200
|
+
if (isProfileDocument(item)) {
|
|
201
|
+
const compiled = compileProfileDocument(item);
|
|
202
|
+
result.profiles.push(...compiled.payload.profiles);
|
|
203
|
+
result.layouts.push(...compiled.payload.layouts);
|
|
204
|
+
result.profileLayouts.push(...compiled.payload.profileLayouts);
|
|
205
|
+
} else if (isUsersDocument(item)) {
|
|
206
|
+
const compiled = compileUsersDocument(item);
|
|
207
|
+
result.users.push(...compiled.payload.users);
|
|
208
|
+
} else if (isLayoutsDocument(item)) {
|
|
209
|
+
const compiled = compileLayoutsDocument(item);
|
|
210
|
+
result.layouts.push(...compiled.payload.layouts);
|
|
406
211
|
}
|
|
407
212
|
}
|
|
213
|
+
result.owner = bundle.owner;
|
|
214
|
+
result.notificationEmail = bundle.notificationEmail;
|
|
215
|
+
} else {
|
|
216
|
+
throw new Error("Unknown document type. Expected profile, users, layouts, or bundle at root.");
|
|
408
217
|
}
|
|
409
|
-
return
|
|
410
|
-
}
|
|
411
|
-
function buildLayoutDtos(workspace) {
|
|
412
|
-
const layouts = collectLayouts(workspace);
|
|
413
|
-
return layouts.map((L) => ({
|
|
414
|
-
context: L.context,
|
|
415
|
-
grid: L.grid,
|
|
416
|
-
value: JSON.stringify(L.value),
|
|
417
|
-
default: L.default,
|
|
418
|
-
public: L.public,
|
|
419
|
-
userGroup: L.userGroup,
|
|
420
|
-
isOwner: true,
|
|
421
|
-
isNew: true,
|
|
422
|
-
name: L.name,
|
|
423
|
-
code: L.code
|
|
424
|
-
}));
|
|
425
|
-
}
|
|
426
|
-
function buildProfileLayoutDtos(workspace, profileCode) {
|
|
427
|
-
const layouts = collectLayouts(workspace);
|
|
428
|
-
return layouts.filter((L) => L.default && L.code).map((L) => ({
|
|
429
|
-
profileCode,
|
|
430
|
-
layoutCode: L.code,
|
|
431
|
-
default: true,
|
|
432
|
-
public: false,
|
|
433
|
-
name: L.componentId
|
|
434
|
-
}));
|
|
435
|
-
}
|
|
436
|
-
function compileProfile(profile) {
|
|
437
|
-
const theme = profile.theme || { color: "default", scheme: "sdtd" };
|
|
438
|
-
const shared = profile.shared || { global: false, userGroup: "" };
|
|
439
|
-
const route = profile.route || {
|
|
440
|
-
profile: "default",
|
|
441
|
-
calculateRoutes: true,
|
|
442
|
-
showSequenceIndicators: true,
|
|
443
|
-
unitOfDistance: "km"
|
|
444
|
-
};
|
|
445
|
-
const planning = profile.planning || {
|
|
446
|
-
snapInterval: { mode: "1hour", value: 0 },
|
|
447
|
-
range: { mode: "week", value: 0 },
|
|
448
|
-
start: { mode: "startOfWeek", value: 2 },
|
|
449
|
-
hours: { start: 8, end: 18 }
|
|
450
|
-
};
|
|
451
|
-
const workspace = profile.workspace || [];
|
|
452
|
-
const goldenLayout = workspaceToGoldenLayout(workspace);
|
|
453
|
-
const layouts = buildLayoutDtos(workspace);
|
|
454
|
-
const profileLayouts = buildProfileLayoutDtos(workspace, profile.code || "");
|
|
455
|
-
return {
|
|
456
|
-
profile: {
|
|
457
|
-
name: profile.name || "",
|
|
458
|
-
code: profile.code || "",
|
|
459
|
-
color: theme.color || "default",
|
|
460
|
-
theme: theme.scheme || "sdtd",
|
|
461
|
-
public: shared.global ?? false,
|
|
462
|
-
userGroup: shared.userGroup || "",
|
|
463
|
-
snapMode: mapSnapMode(planning.snapInterval?.mode),
|
|
464
|
-
snapValue: planning.snapInterval?.value ?? null,
|
|
465
|
-
rangeMode: mapRangeMode(planning.range?.mode),
|
|
466
|
-
rangeValue: planning.range?.value ?? null,
|
|
467
|
-
startMode: mapStartMode(planning.start?.mode),
|
|
468
|
-
startValue: planning.start?.value ?? null,
|
|
469
|
-
startTime: planning.hours?.start ?? 8,
|
|
470
|
-
endTime: planning.hours?.end ?? 18,
|
|
471
|
-
unitOfDistance: mapUnitOfDistance(route.unitOfDistance),
|
|
472
|
-
autoRouteCalculation: route.calculateRoutes ?? true,
|
|
473
|
-
showSequenceIndicators: route.showSequenceIndicators ?? true,
|
|
474
|
-
routeProfile: route.profile || "default",
|
|
475
|
-
layout: JSON.stringify(goldenLayout)
|
|
476
|
-
},
|
|
477
|
-
layouts,
|
|
478
|
-
profileLayouts,
|
|
479
|
-
users: profile.users || [],
|
|
480
|
-
owner: profile.owner,
|
|
481
|
-
notificationEmail: profile.notificationEmail
|
|
482
|
-
};
|
|
218
|
+
return result;
|
|
483
219
|
}
|
|
484
220
|
|
|
485
221
|
// src/commands/validate.ts
|
|
@@ -487,9 +223,9 @@ var validateCommand = new Command("validate").description("Validate a configurat
|
|
|
487
223
|
try {
|
|
488
224
|
const filePath = resolve(normalize(file));
|
|
489
225
|
const content = readFileSync(filePath, "utf-8");
|
|
490
|
-
let
|
|
226
|
+
let doc;
|
|
491
227
|
try {
|
|
492
|
-
|
|
228
|
+
doc = JSON5.parse(content);
|
|
493
229
|
} catch {
|
|
494
230
|
if (options.json) {
|
|
495
231
|
console.log(JSON.stringify({ valid: false, errors: [{ type: "error", message: "Invalid JSON5 syntax" }], warnings: [] }));
|
|
@@ -498,7 +234,7 @@ var validateCommand = new Command("validate").description("Validate a configurat
|
|
|
498
234
|
}
|
|
499
235
|
process.exit(1);
|
|
500
236
|
}
|
|
501
|
-
const result = validateProfile(
|
|
237
|
+
const result = validateProfile(doc);
|
|
502
238
|
if (options.json) {
|
|
503
239
|
console.log(JSON.stringify(result, null, 2));
|
|
504
240
|
} else {
|
|
@@ -543,15 +279,20 @@ var compileCommand = new Command2("compile").description("Compile a JSON5 config
|
|
|
543
279
|
try {
|
|
544
280
|
const filePath = resolve2(normalize2(file));
|
|
545
281
|
const content = readFileSync2(filePath, "utf-8");
|
|
546
|
-
let
|
|
282
|
+
let doc;
|
|
547
283
|
try {
|
|
548
|
-
|
|
284
|
+
doc = JSON52.parse(content);
|
|
549
285
|
} catch {
|
|
550
286
|
console.error(pc2.red("Error:"), "Invalid JSON5 syntax in", file);
|
|
551
287
|
process.exit(1);
|
|
552
288
|
}
|
|
289
|
+
const docType = detectDocumentType(doc);
|
|
290
|
+
if (!docType) {
|
|
291
|
+
console.error(pc2.red("Error:"), "Unknown document type. Expected profile, users, layouts, or bundle at root.");
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
553
294
|
if (!options.skipValidation) {
|
|
554
|
-
const validation = validateProfile(
|
|
295
|
+
const validation = validateProfile(doc);
|
|
555
296
|
if (!validation.valid) {
|
|
556
297
|
console.error(pc2.red("Error:"), "Configuration has validation errors:");
|
|
557
298
|
for (const error of validation.errors) {
|
|
@@ -562,8 +303,8 @@ var compileCommand = new Command2("compile").description("Compile a JSON5 config
|
|
|
562
303
|
process.exit(1);
|
|
563
304
|
}
|
|
564
305
|
}
|
|
565
|
-
const
|
|
566
|
-
const jsonOutput = JSON.stringify(
|
|
306
|
+
const result = compileToApiPayload(doc);
|
|
307
|
+
const jsonOutput = JSON.stringify(result, null, 2);
|
|
567
308
|
if (options.stdout) {
|
|
568
309
|
console.log(jsonOutput);
|
|
569
310
|
} else {
|
|
@@ -572,7 +313,7 @@ var compileCommand = new Command2("compile").description("Compile a JSON5 config
|
|
|
572
313
|
const outputPath = resolve2(outputDir, `${inputBasename}.json`);
|
|
573
314
|
mkdirSync(outputDir, { recursive: true });
|
|
574
315
|
writeFileSync(outputPath, jsonOutput, "utf-8");
|
|
575
|
-
console.log(pc2.green("\u2713"),
|
|
316
|
+
console.log(pc2.green("\u2713"), `Compiled ${docType} document to`, outputPath);
|
|
576
317
|
}
|
|
577
318
|
process.exit(0);
|
|
578
319
|
} catch (err) {
|
|
@@ -605,7 +346,7 @@ async function confirm(message) {
|
|
|
605
346
|
});
|
|
606
347
|
});
|
|
607
348
|
}
|
|
608
|
-
async function deployToApi(
|
|
349
|
+
async function deployToApi(result, docType, url, apiKey) {
|
|
609
350
|
try {
|
|
610
351
|
const response = await fetch(`${url}/import/setup`, {
|
|
611
352
|
method: "POST",
|
|
@@ -613,10 +354,10 @@ async function deployToApi(payload, url, apiKey) {
|
|
|
613
354
|
"Content-Type": "application/json",
|
|
614
355
|
"X-API-KEY": apiKey
|
|
615
356
|
},
|
|
616
|
-
body: JSON.stringify(
|
|
357
|
+
body: JSON.stringify(result)
|
|
617
358
|
});
|
|
618
359
|
if (response.ok) {
|
|
619
|
-
return { success: true, message:
|
|
360
|
+
return { success: true, message: `${docType} document deployed successfully` };
|
|
620
361
|
} else {
|
|
621
362
|
const text = await response.text();
|
|
622
363
|
return { success: false, message: `HTTP ${response.status}`, error: text };
|
|
@@ -648,9 +389,9 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
|
|
|
648
389
|
process.exit(1);
|
|
649
390
|
}
|
|
650
391
|
const apiUrl = ENVIRONMENT_URLS[options.env];
|
|
651
|
-
let
|
|
392
|
+
let doc;
|
|
652
393
|
try {
|
|
653
|
-
|
|
394
|
+
doc = JSON53.parse(content);
|
|
654
395
|
} catch {
|
|
655
396
|
if (options.json) {
|
|
656
397
|
console.log(JSON.stringify({ success: false, error: "Invalid JSON5 syntax" }));
|
|
@@ -659,8 +400,17 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
|
|
|
659
400
|
}
|
|
660
401
|
process.exit(1);
|
|
661
402
|
}
|
|
662
|
-
|
|
663
|
-
|
|
403
|
+
const docType = detectDocumentType(doc);
|
|
404
|
+
if (!docType) {
|
|
405
|
+
if (options.json) {
|
|
406
|
+
console.log(JSON.stringify({ success: false, error: "Unknown document type. Expected profile, users, or layouts at root." }));
|
|
407
|
+
} else {
|
|
408
|
+
console.error(pc3.red("Error:"), "Unknown document type. Expected profile, users, or layouts at root.");
|
|
409
|
+
}
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
if (!options.skipValidation && isProfileDocument(doc)) {
|
|
413
|
+
const validation = validateProfile(doc);
|
|
664
414
|
if (!validation.valid) {
|
|
665
415
|
if (options.json) {
|
|
666
416
|
console.log(JSON.stringify({ success: false, error: "Validation failed", details: validation.errors }));
|
|
@@ -673,12 +423,12 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
|
|
|
673
423
|
process.exit(1);
|
|
674
424
|
}
|
|
675
425
|
}
|
|
676
|
-
const
|
|
426
|
+
const result = compileToApiPayload(doc);
|
|
677
427
|
if (options.dryRun) {
|
|
678
428
|
if (options.json) {
|
|
679
|
-
console.log(JSON.stringify({ success: true, message: "Dry run successful",
|
|
429
|
+
console.log(JSON.stringify({ success: true, message: "Dry run successful", result }));
|
|
680
430
|
} else {
|
|
681
|
-
console.log(pc3.green("\u2713"),
|
|
431
|
+
console.log(pc3.green("\u2713"), `Dry run successful - ${docType} document is valid and compiled`);
|
|
682
432
|
console.log(pc3.dim(" Would deploy to:"), apiUrl);
|
|
683
433
|
}
|
|
684
434
|
process.exit(0);
|
|
@@ -686,7 +436,10 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
|
|
|
686
436
|
if (!options.yes && !options.json) {
|
|
687
437
|
console.log();
|
|
688
438
|
console.log(pc3.bold("Deploy Summary:"));
|
|
689
|
-
console.log(`
|
|
439
|
+
console.log(` Document type: ${pc3.cyan(docType)}`);
|
|
440
|
+
if (isProfileDocument(doc)) {
|
|
441
|
+
console.log(` Profile: ${pc3.cyan(doc.payload.name || "unnamed")} (${doc.payload.code || "no code"})`);
|
|
442
|
+
}
|
|
690
443
|
console.log(` Environment: ${pc3.yellow(options.env)}`);
|
|
691
444
|
console.log(` Target: ${pc3.dim(apiUrl)}`);
|
|
692
445
|
console.log();
|
|
@@ -699,20 +452,20 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
|
|
|
699
452
|
if (!options.json) {
|
|
700
453
|
console.log(pc3.dim("Deploying..."));
|
|
701
454
|
}
|
|
702
|
-
const
|
|
455
|
+
const deployResult = await deployToApi(result, docType, apiUrl, apiKey);
|
|
703
456
|
if (options.json) {
|
|
704
|
-
console.log(JSON.stringify(
|
|
457
|
+
console.log(JSON.stringify(deployResult));
|
|
705
458
|
} else {
|
|
706
|
-
if (
|
|
707
|
-
console.log(pc3.green("\u2713"),
|
|
459
|
+
if (deployResult.success) {
|
|
460
|
+
console.log(pc3.green("\u2713"), deployResult.message);
|
|
708
461
|
} else {
|
|
709
|
-
console.error(pc3.red("\u2717"),
|
|
710
|
-
if (
|
|
711
|
-
console.error(pc3.dim(" "),
|
|
462
|
+
console.error(pc3.red("\u2717"), deployResult.message);
|
|
463
|
+
if (deployResult.error) {
|
|
464
|
+
console.error(pc3.dim(" "), deployResult.error);
|
|
712
465
|
}
|
|
713
466
|
}
|
|
714
467
|
}
|
|
715
|
-
process.exit(
|
|
468
|
+
process.exit(deployResult.success ? 0 : 2);
|
|
716
469
|
} catch (err) {
|
|
717
470
|
if (options.json) {
|
|
718
471
|
console.log(JSON.stringify({ success: false, error: String(err) }));
|
|
@@ -725,8 +478,12 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
|
|
|
725
478
|
|
|
726
479
|
// src/index.ts
|
|
727
480
|
var program = new Command4();
|
|
728
|
-
program.name("dimescheduler-setup").description("CLI tool to validate, compile, and deploy Dime.Scheduler configurations").version("0.1.
|
|
481
|
+
program.name("dimescheduler-setup").description("CLI tool to validate, compile, and deploy Dime.Scheduler configurations").version("0.1.3");
|
|
729
482
|
program.addCommand(validateCommand);
|
|
730
483
|
program.addCommand(compileCommand);
|
|
731
484
|
program.addCommand(deployCommand);
|
|
485
|
+
if (process.argv.length <= 2) {
|
|
486
|
+
program.outputHelp();
|
|
487
|
+
process.exit(0);
|
|
488
|
+
}
|
|
732
489
|
program.parse();
|