@dimescheduler/setup 0.1.2 → 0.11.4

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/index.js CHANGED
@@ -1,4 +1,17 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ compileConfigurationDocument,
4
+ compileLayoutsDocument,
5
+ compileProfileDocument,
6
+ compileUsersDocument,
7
+ detectDocumentType,
8
+ isBundleDocument,
9
+ isConfigurationDocument,
10
+ isDocumentReference,
11
+ isLayoutsDocument,
12
+ isProfileDocument,
13
+ isUsersDocument
14
+ } from "./chunk-3PMKH6IT.js";
2
15
 
3
16
  // src/index.ts
4
17
  import { Command as Command4 } from "commander";
@@ -34,452 +47,186 @@ function hasComponent(nodes, componentType) {
34
47
  }
35
48
  return false;
36
49
  }
37
- function validateProfile(profile) {
50
+ function validateProfileSettings(settings, prefix = "") {
38
51
  const issues = [];
39
- if (!profile.name?.trim()) {
40
- issues.push({ type: "error", message: "Profile name is required" });
52
+ const p = prefix ? `${prefix}: ` : "";
53
+ if (!settings.name?.trim()) {
54
+ issues.push({ type: "error", message: `${p}Profile name is required` });
41
55
  }
42
- if (!profile.code?.trim()) {
43
- issues.push({ type: "error", message: "Profile code is required" });
56
+ if (!settings.code?.trim()) {
57
+ issues.push({ type: "error", message: `${p}Profile code is required` });
44
58
  }
45
- if (!profile.workspace || profile.workspace.length === 0) {
46
- issues.push({ type: "error", message: "Workspace must have at least one element" });
59
+ if (!settings.workspace || settings.workspace.length === 0) {
60
+ issues.push({ type: "error", message: `${p}Workspace must have at least one element` });
47
61
  } else {
48
- const componentCount = countComponents(profile.workspace);
62
+ const componentCount = countComponents(settings.workspace);
49
63
  if (componentCount === 0) {
50
- issues.push({ type: "warning", message: "Workspace has no components" });
64
+ issues.push({ type: "warning", message: `${p}Workspace has no components` });
51
65
  }
52
- const hasPlanningBoard = hasComponent(profile.workspace, "planningBoard");
66
+ const hasPlanningBoard = hasComponent(settings.workspace, "planningBoard");
53
67
  if (!hasPlanningBoard) {
54
- issues.push({ type: "warning", message: "Consider adding a Planning Board component" });
68
+ issues.push({ type: "warning", message: `${p}Consider adding a Planning Board component` });
55
69
  }
56
70
  }
57
- if (profile.users && profile.users.length > 0) {
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;
71
+ return issues;
181
72
  }
182
- function mapStartMode(mode) {
183
- if (!mode) return 2;
184
- return START_MODE_MAP[mode.toLowerCase().replace(/\s+/g, "")] ?? 2;
185
- }
186
- function mapUnitOfDistance(unit) {
187
- if (!unit) return "Kilometers";
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);
73
+ function validateUsers(users, prefix = "") {
74
+ const issues = [];
75
+ const p = prefix ? `${prefix} ` : "";
76
+ users.forEach((user, index) => {
77
+ if (!user.name?.trim()) {
78
+ issues.push({ type: "error", message: `${p}User ${index + 1}: Name is required` });
225
79
  }
226
- if (node.type === "stack") {
227
- gl.activeItemIndex = 0;
80
+ if (!user.email?.trim()) {
81
+ issues.push({ type: "error", message: `${p}User ${index + 1}: Email is required` });
228
82
  }
229
- return gl;
83
+ });
84
+ return issues;
85
+ }
86
+ function validateProfile(doc) {
87
+ const issues = [];
88
+ if (!doc || typeof doc !== "object") {
89
+ issues.push({ type: "error", message: "Invalid document: expected an object" });
90
+ return { valid: false, errors: issues, warnings: [] };
230
91
  }
231
- if (node.type === "component") {
232
- const compName = componentToGlName(node.component);
233
- if (compName) {
234
- gl.componentName = compName;
92
+ const obj = doc;
93
+ const docType = obj.type;
94
+ switch (docType) {
95
+ case "profile": {
96
+ if (!obj.payload || typeof obj.payload !== "object") {
97
+ issues.push({ type: "error", message: 'Profile document must have a "payload" property' });
98
+ } else {
99
+ issues.push(...validateProfileSettings(obj.payload));
100
+ }
101
+ break;
235
102
  }
236
- if (node.title !== void 0) {
237
- gl.title = node.title;
103
+ case "users": {
104
+ if (!Array.isArray(obj.payload)) {
105
+ issues.push({ type: "error", message: 'Users document must have a "payload" array' });
106
+ } else {
107
+ issues.push(...validateUsers(obj.payload));
108
+ }
109
+ break;
238
110
  }
239
- gl.isClosable = true;
240
- gl.reorderEnabled = true;
241
- const compState = {};
242
- const compId = node.id;
243
- if (compId) {
244
- gl.id = compId;
245
- compState.id = compId;
246
- } else if (compName === "schedulerComponent") {
247
- gl.id = "schedulerContainer";
248
- compState.id = "scheduler";
111
+ case "layouts": {
112
+ if (!Array.isArray(obj.payload)) {
113
+ issues.push({ type: "error", message: 'Layouts document must have a "payload" array' });
114
+ }
115
+ break;
249
116
  }
250
- if (compName === "datePickerComponent" && compId) {
251
- compState.wrapperId = compId;
117
+ case "bundle": {
118
+ if (!obj.name?.toString().trim()) {
119
+ issues.push({ type: "error", message: "Bundle name is required" });
120
+ }
121
+ if (!Array.isArray(obj.documents)) {
122
+ issues.push({ type: "error", message: 'Bundle must have a "documents" array' });
123
+ } else {
124
+ const documents = obj.documents;
125
+ let profileCount = 0;
126
+ documents.forEach((item, index) => {
127
+ if ("$ref" in item) {
128
+ if (typeof item.$ref !== "string") {
129
+ issues.push({ type: "error", message: `Document ${index + 1}: $ref must be a string` });
130
+ }
131
+ } else if (item.type === "profile") {
132
+ profileCount++;
133
+ if (item.payload && typeof item.payload === "object") {
134
+ const profileName = item.payload.name || `Profile ${profileCount}`;
135
+ issues.push(...validateProfileSettings(item.payload, profileName));
136
+ } else {
137
+ issues.push({ type: "error", message: `Document ${index + 1}: Profile must have a "payload" property` });
138
+ }
139
+ } else if (item.type === "users") {
140
+ if (Array.isArray(item.payload)) {
141
+ issues.push(...validateUsers(item.payload));
142
+ }
143
+ }
144
+ });
145
+ if (profileCount === 0) {
146
+ issues.push({ type: "warning", message: "Bundle contains no profile documents" });
147
+ }
148
+ }
149
+ break;
252
150
  }
253
- if (Object.keys(compState).length > 0) {
254
- gl.componentState = compState;
151
+ default: {
152
+ issues.push(...validateProfileSettings({
153
+ name: obj.name,
154
+ code: obj.code,
155
+ workspace: obj.workspace
156
+ }));
157
+ if (Array.isArray(obj.users)) {
158
+ issues.push(...validateUsers(obj.users));
159
+ }
255
160
  }
256
- return gl;
257
161
  }
258
- return gl;
259
- }
260
- function workspaceToGoldenLayout(workspace) {
162
+ const errors = issues.filter((i) => i.type === "error");
163
+ const warnings = issues.filter((i) => i.type === "warning");
261
164
  return {
262
- settings: {
263
- hasHeaders: true,
264
- constrainDragToContainer: false,
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
165
+ valid: errors.length === 0,
166
+ errors,
167
+ warnings
309
168
  };
310
169
  }
311
- function buildLayoutState(layout, gridName) {
312
- const columns = (layout.columns || []).filter((c) => c.property).map((c) => ({ dataIndex: c.property }));
313
- const sorters = (layout.sorters || []).filter((s) => s.property && s.direction).map((s) => ({ direction: s.direction, property: s.property }));
314
- let grouper = null;
315
- if (layout.grouper && layout.grouper.property && layout.grouper.direction) {
316
- grouper = {
317
- root: "data",
318
- property: layout.grouper.property,
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
170
+
171
+ // src/core/compile/index.ts
172
+ function compileToApiPayload(doc) {
173
+ const result = {
174
+ profiles: [],
175
+ layouts: [],
176
+ profileLayouts: [],
177
+ users: [],
178
+ configuration: []
344
179
  };
345
- if (sorters.length > 0) {
346
- state.sorters = sorters;
347
- }
348
- if (layout.default) {
349
- state.default = true;
350
- }
351
- if (layout.name) {
352
- state.name = layout.name;
353
- }
354
- const extraFields = [
355
- "viewLayoutType",
356
- "startRowGroupsCollapsed",
357
- "startColGroupsCollapsed",
358
- "enableColumnSort",
359
- "expandedItems",
360
- "matrix",
361
- "pivotcolumns",
362
- "collapsed",
363
- "hideEmptyRows"
364
- ];
365
- for (const field of extraFields) {
366
- if (layout[field] !== void 0) {
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));
180
+ if (isProfileDocument(doc)) {
181
+ const compiled = compileProfileDocument(doc);
182
+ result.profiles = compiled.payload.profiles;
183
+ result.layouts = compiled.payload.layouts;
184
+ result.profileLayouts = compiled.payload.profileLayouts;
185
+ result.owner = compiled.payload.owner;
186
+ result.notificationEmail = compiled.payload.notificationEmail;
187
+ } else if (isUsersDocument(doc)) {
188
+ const compiled = compileUsersDocument(doc);
189
+ result.users = compiled.payload.users;
190
+ result.owner = compiled.payload.owner;
191
+ result.notificationEmail = compiled.payload.notificationEmail;
192
+ } else if (isLayoutsDocument(doc)) {
193
+ const compiled = compileLayoutsDocument(doc);
194
+ result.layouts = compiled.payload.layouts;
195
+ result.owner = compiled.payload.owner;
196
+ result.notificationEmail = compiled.payload.notificationEmail;
197
+ } else if (isConfigurationDocument(doc)) {
198
+ const compiled = compileConfigurationDocument(doc);
199
+ result.configuration = compiled.payload.configuration;
200
+ result.owner = compiled.payload.owner;
201
+ result.notificationEmail = compiled.payload.notificationEmail;
202
+ } else if (isBundleDocument(doc)) {
203
+ const bundle = doc;
204
+ for (const item of bundle.documents) {
205
+ if (isDocumentReference(item)) {
206
+ throw new Error("Bundle contains $ref items. Use compileToApiPayloadAsync instead.");
378
207
  }
379
- } else if (node.type === "component") {
380
- const layouts = node.layouts || [];
381
- const layoutArray = Array.isArray(layouts) ? layouts : [layouts];
382
- for (const layoutItem of layoutArray) {
383
- const context = componentToContext(node.component);
384
- let gridName;
385
- if (node.component === "planningBoard" && !layoutItem.id) {
386
- gridName = "scheduler_panel";
387
- } else {
388
- gridName = layoutItem.id || `${node.id}_panel`;
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
- });
208
+ if (isProfileDocument(item)) {
209
+ const compiled = compileProfileDocument(item);
210
+ result.profiles.push(...compiled.payload.profiles);
211
+ result.layouts.push(...compiled.payload.layouts);
212
+ result.profileLayouts.push(...compiled.payload.profileLayouts);
213
+ } else if (isUsersDocument(item)) {
214
+ const compiled = compileUsersDocument(item);
215
+ result.users.push(...compiled.payload.users);
216
+ } else if (isLayoutsDocument(item)) {
217
+ const compiled = compileLayoutsDocument(item);
218
+ result.layouts.push(...compiled.payload.layouts);
219
+ } else if (isConfigurationDocument(item)) {
220
+ const compiled = compileConfigurationDocument(item);
221
+ result.configuration.push(...compiled.payload.configuration);
406
222
  }
407
223
  }
224
+ result.owner = bundle.owner;
225
+ result.notificationEmail = bundle.notificationEmail;
226
+ } else {
227
+ throw new Error("Unknown document type. Expected profile, users, layouts, configuration, or bundle at root.");
408
228
  }
409
- return acc;
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
- };
229
+ return result;
483
230
  }
484
231
 
485
232
  // src/commands/validate.ts
@@ -487,9 +234,9 @@ var validateCommand = new Command("validate").description("Validate a configurat
487
234
  try {
488
235
  const filePath = resolve(normalize(file));
489
236
  const content = readFileSync(filePath, "utf-8");
490
- let profile;
237
+ let doc;
491
238
  try {
492
- profile = JSON5.parse(content);
239
+ doc = JSON5.parse(content);
493
240
  } catch {
494
241
  if (options.json) {
495
242
  console.log(JSON.stringify({ valid: false, errors: [{ type: "error", message: "Invalid JSON5 syntax" }], warnings: [] }));
@@ -498,7 +245,7 @@ var validateCommand = new Command("validate").description("Validate a configurat
498
245
  }
499
246
  process.exit(1);
500
247
  }
501
- const result = validateProfile(profile);
248
+ const result = validateProfile(doc);
502
249
  if (options.json) {
503
250
  console.log(JSON.stringify(result, null, 2));
504
251
  } else {
@@ -543,15 +290,20 @@ var compileCommand = new Command2("compile").description("Compile a JSON5 config
543
290
  try {
544
291
  const filePath = resolve2(normalize2(file));
545
292
  const content = readFileSync2(filePath, "utf-8");
546
- let profile;
293
+ let doc;
547
294
  try {
548
- profile = JSON52.parse(content);
295
+ doc = JSON52.parse(content);
549
296
  } catch {
550
297
  console.error(pc2.red("Error:"), "Invalid JSON5 syntax in", file);
551
298
  process.exit(1);
552
299
  }
300
+ const docType = detectDocumentType(doc);
301
+ if (!docType) {
302
+ console.error(pc2.red("Error:"), "Unknown document type. Expected profile, users, layouts, or bundle at root.");
303
+ process.exit(1);
304
+ }
553
305
  if (!options.skipValidation) {
554
- const validation = validateProfile(profile);
306
+ const validation = validateProfile(doc);
555
307
  if (!validation.valid) {
556
308
  console.error(pc2.red("Error:"), "Configuration has validation errors:");
557
309
  for (const error of validation.errors) {
@@ -562,8 +314,8 @@ var compileCommand = new Command2("compile").description("Compile a JSON5 config
562
314
  process.exit(1);
563
315
  }
564
316
  }
565
- const payload = compileProfile(profile);
566
- const jsonOutput = JSON.stringify(payload, null, 2);
317
+ const result = compileToApiPayload(doc);
318
+ const jsonOutput = JSON.stringify(result, null, 2);
567
319
  if (options.stdout) {
568
320
  console.log(jsonOutput);
569
321
  } else {
@@ -572,7 +324,7 @@ var compileCommand = new Command2("compile").description("Compile a JSON5 config
572
324
  const outputPath = resolve2(outputDir, `${inputBasename}.json`);
573
325
  mkdirSync(outputDir, { recursive: true });
574
326
  writeFileSync(outputPath, jsonOutput, "utf-8");
575
- console.log(pc2.green("\u2713"), "Compiled to", outputPath);
327
+ console.log(pc2.green("\u2713"), `Compiled ${docType} document to`, outputPath);
576
328
  }
577
329
  process.exit(0);
578
330
  } catch (err) {
@@ -605,7 +357,7 @@ async function confirm(message) {
605
357
  });
606
358
  });
607
359
  }
608
- async function deployToApi(payload, url, apiKey) {
360
+ async function deployToApi(result, docType, url, apiKey) {
609
361
  try {
610
362
  const response = await fetch(`${url}/import/setup`, {
611
363
  method: "POST",
@@ -613,10 +365,10 @@ async function deployToApi(payload, url, apiKey) {
613
365
  "Content-Type": "application/json",
614
366
  "X-API-KEY": apiKey
615
367
  },
616
- body: JSON.stringify(payload)
368
+ body: JSON.stringify(result)
617
369
  });
618
370
  if (response.ok) {
619
- return { success: true, message: "Profile deployed successfully" };
371
+ return { success: true, message: `${docType} document deployed successfully` };
620
372
  } else {
621
373
  const text = await response.text();
622
374
  return { success: false, message: `HTTP ${response.status}`, error: text };
@@ -648,9 +400,9 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
648
400
  process.exit(1);
649
401
  }
650
402
  const apiUrl = ENVIRONMENT_URLS[options.env];
651
- let profile;
403
+ let doc;
652
404
  try {
653
- profile = JSON53.parse(content);
405
+ doc = JSON53.parse(content);
654
406
  } catch {
655
407
  if (options.json) {
656
408
  console.log(JSON.stringify({ success: false, error: "Invalid JSON5 syntax" }));
@@ -659,8 +411,17 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
659
411
  }
660
412
  process.exit(1);
661
413
  }
662
- if (!options.skipValidation) {
663
- const validation = validateProfile(profile);
414
+ const docType = detectDocumentType(doc);
415
+ if (!docType) {
416
+ if (options.json) {
417
+ console.log(JSON.stringify({ success: false, error: "Unknown document type. Expected profile, users, or layouts at root." }));
418
+ } else {
419
+ console.error(pc3.red("Error:"), "Unknown document type. Expected profile, users, or layouts at root.");
420
+ }
421
+ process.exit(1);
422
+ }
423
+ if (!options.skipValidation && isProfileDocument(doc)) {
424
+ const validation = validateProfile(doc);
664
425
  if (!validation.valid) {
665
426
  if (options.json) {
666
427
  console.log(JSON.stringify({ success: false, error: "Validation failed", details: validation.errors }));
@@ -673,12 +434,12 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
673
434
  process.exit(1);
674
435
  }
675
436
  }
676
- const payload = compileProfile(profile);
437
+ const result = compileToApiPayload(doc);
677
438
  if (options.dryRun) {
678
439
  if (options.json) {
679
- console.log(JSON.stringify({ success: true, message: "Dry run successful", payload }));
440
+ console.log(JSON.stringify({ success: true, message: "Dry run successful", result }));
680
441
  } else {
681
- console.log(pc3.green("\u2713"), "Dry run successful - configuration is valid and compiled");
442
+ console.log(pc3.green("\u2713"), `Dry run successful - ${docType} document is valid and compiled`);
682
443
  console.log(pc3.dim(" Would deploy to:"), apiUrl);
683
444
  }
684
445
  process.exit(0);
@@ -686,7 +447,10 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
686
447
  if (!options.yes && !options.json) {
687
448
  console.log();
688
449
  console.log(pc3.bold("Deploy Summary:"));
689
- console.log(` Profile: ${pc3.cyan(profile.name || "unnamed")} (${profile.code || "no code"})`);
450
+ console.log(` Document type: ${pc3.cyan(docType)}`);
451
+ if (isProfileDocument(doc)) {
452
+ console.log(` Profile: ${pc3.cyan(doc.payload.name || "unnamed")} (${doc.payload.code || "no code"})`);
453
+ }
690
454
  console.log(` Environment: ${pc3.yellow(options.env)}`);
691
455
  console.log(` Target: ${pc3.dim(apiUrl)}`);
692
456
  console.log();
@@ -699,20 +463,20 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
699
463
  if (!options.json) {
700
464
  console.log(pc3.dim("Deploying..."));
701
465
  }
702
- const result = await deployToApi(payload, apiUrl, apiKey);
466
+ const deployResult = await deployToApi(result, docType, apiUrl, apiKey);
703
467
  if (options.json) {
704
- console.log(JSON.stringify(result));
468
+ console.log(JSON.stringify(deployResult));
705
469
  } else {
706
- if (result.success) {
707
- console.log(pc3.green("\u2713"), result.message);
470
+ if (deployResult.success) {
471
+ console.log(pc3.green("\u2713"), deployResult.message);
708
472
  } else {
709
- console.error(pc3.red("\u2717"), result.message);
710
- if (result.error) {
711
- console.error(pc3.dim(" "), result.error);
473
+ console.error(pc3.red("\u2717"), deployResult.message);
474
+ if (deployResult.error) {
475
+ console.error(pc3.dim(" "), deployResult.error);
712
476
  }
713
477
  }
714
478
  }
715
- process.exit(result.success ? 0 : 2);
479
+ process.exit(deployResult.success ? 0 : 2);
716
480
  } catch (err) {
717
481
  if (options.json) {
718
482
  console.log(JSON.stringify({ success: false, error: String(err) }));
@@ -725,8 +489,12 @@ var deployCommand = new Command3("deploy").description("Deploy a configuration t
725
489
 
726
490
  // src/index.ts
727
491
  var program = new Command4();
728
- program.name("dimescheduler-setup").description("CLI tool to validate, compile, and deploy Dime.Scheduler configurations").version("0.1.0");
492
+ program.name("dimescheduler-setup").description("CLI tool to validate, compile, and deploy Dime.Scheduler configurations").version("0.1.3");
729
493
  program.addCommand(validateCommand);
730
494
  program.addCommand(compileCommand);
731
495
  program.addCommand(deployCommand);
496
+ if (process.argv.length <= 2) {
497
+ program.outputHelp();
498
+ process.exit(0);
499
+ }
732
500
  program.parse();