@dimescheduler/setup 0.1.3 → 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.
@@ -2,7 +2,7 @@ import {
2
2
  compileBundleDocument,
3
3
  compileBundleDocumentSync,
4
4
  resolveBundle
5
- } from "./chunk-VHT6HO3N.js";
5
+ } from "./chunk-3PMKH6IT.js";
6
6
  export {
7
7
  compileBundleDocument,
8
8
  compileBundleDocumentSync,
@@ -13,6 +13,9 @@ function isUsersDocument(doc) {
13
13
  function isLayoutsDocument(doc) {
14
14
  return typeof doc === "object" && doc !== null && doc.type === "layouts";
15
15
  }
16
+ function isConfigurationDocument(doc) {
17
+ return typeof doc === "object" && doc !== null && doc.type === "configuration";
18
+ }
16
19
  function isBundleDocument(doc) {
17
20
  return typeof doc === "object" && doc !== null && doc.type === "bundle";
18
21
  }
@@ -22,7 +25,7 @@ function isDocumentReference(item) {
22
25
  function detectDocumentType(doc) {
23
26
  if (typeof doc !== "object" || doc === null) return null;
24
27
  const type = doc.type;
25
- if (type === "profile" || type === "users" || type === "layouts" || type === "bundle") {
28
+ if (type === "profile" || type === "users" || type === "layouts" || type === "configuration" || type === "bundle") {
26
29
  return type;
27
30
  }
28
31
  return null;
@@ -236,9 +239,22 @@ var COMPONENT_TO_GL = {
236
239
  "routeSequenceComponent": "routeSequenceComponent",
237
240
  "notificationsComponent": "notificationsComponent"
238
241
  };
242
+ var CONTEXT_TO_API_CONTEXT = {
243
+ "planningBoard": "scheduler",
244
+ "openTasks": "unplannedTasksGrid",
245
+ "plannedTasks": "plannedTasksGrid",
246
+ "notifications": "notificationsGrid",
247
+ "details": "detailsGrid",
248
+ "capacity": "pivotGrid",
249
+ "gantt": "gantt",
250
+ "routeSequence": "routeSequenceGrid"
251
+ };
239
252
  function componentToGlName(name) {
240
253
  return COMPONENT_TO_GL[name] ?? name;
241
254
  }
255
+ function contextToApiContext(context) {
256
+ return CONTEXT_TO_API_CONTEXT[context] ?? context;
257
+ }
242
258
  var VIEW_PRESET_MAP = {
243
259
  "day": "1",
244
260
  "1": "1",
@@ -496,17 +512,17 @@ function buildGridLayoutState(layout, gridName) {
496
512
  function buildLayoutState(layout, gridName) {
497
513
  const context = layout.context;
498
514
  switch (context) {
499
- case "scheduler":
515
+ case "planningBoard":
500
516
  return buildSchedulerLayoutState(layout, gridName);
501
- case "pivotGrid":
517
+ case "capacity":
502
518
  return buildCapacityLayoutState(layout, gridName);
503
519
  case "gantt":
504
520
  return buildGanttLayoutState(layout, gridName);
505
- case "unplannedTasksGrid":
506
- case "plannedTasksGrid":
507
- case "notificationsGrid":
508
- case "detailsGrid":
509
- case "routeSequenceGrid":
521
+ case "openTasks":
522
+ case "plannedTasks":
523
+ case "notifications":
524
+ case "details":
525
+ case "routeSequence":
510
526
  return buildGridLayoutState(layout, gridName);
511
527
  default:
512
528
  return buildBaseLayoutState(layout, gridName);
@@ -533,7 +549,7 @@ function collectLayouts(layouts) {
533
549
  function buildLayoutDtos(layouts) {
534
550
  if (!layouts || layouts.length === 0) return [];
535
551
  return collectLayouts(layouts).map((L) => ({
536
- context: L.context,
552
+ context: contextToApiContext(L.context),
537
553
  grid: L.grid,
538
554
  value: JSON.stringify(L.value),
539
555
  default: L.default,
@@ -702,12 +718,139 @@ function compileLayoutsDocument(doc) {
702
718
  };
703
719
  }
704
720
 
721
+ // src/core/compile/configuration.ts
722
+ var CONFIG_KEY_TO_INTERNAL = {
723
+ CompanyName: "AppSetup_CompanyName",
724
+ CompanyAddress: "AppSetup_CompanyAddress",
725
+ CompanyAddressCountry: "AppSetup_CompanyAddress_Country",
726
+ DurationFormat: "AppSetup_DurationFormat",
727
+ EnableAppointmentContainers: "AppSetup_EnableAppointmentContainers",
728
+ EnablePlanningBoardTooltip: "AppSetup_EnablePlanningBoardTooltip",
729
+ ApplyRequestedDates: "AppSetup_ApplyRequestedDates",
730
+ ApplyRequestedTimes: "AppSetup_ApplyRequestedTimes",
731
+ RespectAllowedDateConstraints: "AppSetup_RespectAllowedDateConstraints",
732
+ MultiDayCapacityDistributionMode: "AppSetup_MultiDayCapacityDistributionMode",
733
+ RenderCategoryInBackground: "AppSetup_RenderCategoryInBackground",
734
+ AlternateRows: "AppSetup_AlternateRows",
735
+ EnableResourceCalendarsVisualisation: "AppSetup_EnableResourceCalendarsVisualisation",
736
+ ResourceZonesColor: "AppSetup_ResourceZonesColor",
737
+ ResourceCalendarRecalculationMode: "AppSetup_ResourceCalendarRecalculationMode",
738
+ RouteReschedulingMode: "AppSetup_RouteReschedulingMode",
739
+ DoNotCountAssignment: "AppSetup_DoNotCountAssignment",
740
+ DisableTaskDurationCalculation: "AppSetup_DisableTaskDurationCalculation",
741
+ CalculateRouteAndTravelTime: "AppSetup_CalculateRouteAndTravelTime",
742
+ DistanceUnit: "AppSetup_DistanceUnit",
743
+ RouteProfile: "AppSetup_RouteProfile",
744
+ ShowWaypoints: "AppSetup_ShowWaypoints",
745
+ MobileVisibilityModeForLockedAppointments: "AppSetup_MobileVisibilityModeForLockedAppointments",
746
+ SolverApiKey: "AppSetup_SolverApiKey",
747
+ EnableRouteModel: "AppSetup_EnableRouteModel",
748
+ EnableFieldServiceModel: "AppSetup_EnableFieldServiceModel",
749
+ Chat: "AppSetup_Chat",
750
+ OpenAiApiKey: "AppSetup_OpenAiApiKey",
751
+ ExchangeClientId: "AppSetup_Exchange_ClientId",
752
+ ExchangeClientSecret: "AppSetup_Exchange_ClientSecret",
753
+ ExchangeClientTenant: "AppSetup_Exchange_ClientTenant",
754
+ ExchangeEnableTwoWaySync: "AppSetup_Exchange_EnableTwoWaySync",
755
+ ExchangeDeltaStart: "AppSetup_Exchange_DeltaStart",
756
+ ExchangeDeltaEnd: "AppSetup_Exchange_DeltaEnd",
757
+ ExchangeResourcePreferencesEnabled: "AppSetup_Exchange_ResourcePreferences_Enabled",
758
+ ExchangeDefaultShowAs: "AppSetup_Exchange_ResourcePreferences_DefaultShowAs",
759
+ ExchangeDefaultSensitivity: "AppSetup_Exchange_ResourcePreferences_DefaultSensitivity",
760
+ ExchangeCategoryPreset: "AppSetup_Exchange_CategoryPreset",
761
+ ExchangeUseCategory: "AppSetup_Exchange_UseCategory"
762
+ };
763
+ var ENUM_CONVERSIONS = {
764
+ "AppSetup_DurationFormat": {
765
+ "Decimal": 0,
766
+ "HoursMinutes": 1,
767
+ "DaysDecimal": 2,
768
+ "DaysHours": 3
769
+ },
770
+ "AppSetup_ResourceCalendarRecalculationMode": {
771
+ "None": 0,
772
+ "ExtendDuration": 1,
773
+ "UpdatePlanningQuantity": 2
774
+ },
775
+ "AppSetup_DistanceUnit": {
776
+ "km": 0,
777
+ "mi": 1
778
+ },
779
+ "AppSetup_MobileVisibilityModeForLockedAppointments": {
780
+ "Locked": 0,
781
+ "Hidden": 1
782
+ },
783
+ "AppSetup_MultiDayCapacityDistributionMode": {
784
+ "None": 0,
785
+ "Constant": 1,
786
+ "Even": 2
787
+ },
788
+ "AppSetup_RouteReschedulingMode": {
789
+ "DoNothing": 0,
790
+ "UpdateTravelTime": 1,
791
+ "Optimize": 2
792
+ }
793
+ };
794
+ var SHOW_AS_TO_ID = {
795
+ "Free": 1,
796
+ "Tentative": 2,
797
+ "Office": 3,
798
+ "OutOfOffice": 4,
799
+ "WorkingElsewhere": 5,
800
+ "Unknown": 6
801
+ };
802
+ var SENSITIVITY_TO_ID = {
803
+ "Normal": 1,
804
+ "Personal": 2,
805
+ "Private": 3,
806
+ "Confidential": 4
807
+ };
808
+ function convertConfigurationItem(item) {
809
+ const internalKey = CONFIG_KEY_TO_INTERNAL[item.key] || item.key;
810
+ let value = item.value;
811
+ if (internalKey === "AppSetup_Exchange_ResourcePreferences_DefaultShowAs" && Array.isArray(item.value)) {
812
+ const ids = item.value.map((v) => SHOW_AS_TO_ID[v]).filter(Boolean);
813
+ value = ids.sort((a, b) => a - b).join(";");
814
+ } else if (internalKey === "AppSetup_Exchange_ResourcePreferences_DefaultSensitivity" && Array.isArray(item.value)) {
815
+ const ids = item.value.map((v) => SENSITIVITY_TO_ID[v]).filter(Boolean);
816
+ value = ids.sort((a, b) => a - b).join(";");
817
+ } else if (typeof value === "string" && ENUM_CONVERSIONS[internalKey]?.[value] !== void 0) {
818
+ value = ENUM_CONVERSIONS[internalKey][value];
819
+ }
820
+ return {
821
+ key: internalKey,
822
+ value
823
+ };
824
+ }
825
+ function compileConfigurationDocument(doc) {
826
+ const configuration = (doc.payload || []).map(convertConfigurationItem);
827
+ return {
828
+ id: "configuration",
829
+ payload: {
830
+ configuration,
831
+ owner: doc.owner,
832
+ notificationEmail: doc.notificationEmail
833
+ }
834
+ };
835
+ }
836
+ function mergeConfiguration(existing, incoming) {
837
+ const merged = /* @__PURE__ */ new Map();
838
+ for (const item of existing) {
839
+ merged.set(item.key, item);
840
+ }
841
+ for (const item of incoming) {
842
+ merged.set(item.key, item);
843
+ }
844
+ return Array.from(merged.values());
845
+ }
846
+
705
847
  // src/core/compile/bundle.ts
706
848
  async function resolveBundle(bundle, basePath) {
707
849
  const result = {
708
850
  profiles: [],
709
851
  users: [],
710
- layouts: []
852
+ layouts: [],
853
+ configuration: []
711
854
  };
712
855
  const strategy = bundle.mergeStrategy ?? {};
713
856
  for (const item of bundle.documents) {
@@ -716,14 +859,14 @@ async function resolveBundle(bundle, basePath) {
716
859
  const refPath = resolve(dirname(basePath), item.$ref);
717
860
  const content = await readFile(refPath, "utf-8");
718
861
  const parsed = JSON5.parse(content);
719
- if (!isProfileDocument(parsed) && !isUsersDocument(parsed) && !isLayoutsDocument(parsed)) {
720
- throw new Error(`Referenced document at ${item.$ref} is not a valid document type (profile, users, or layouts)`);
862
+ if (!isProfileDocument(parsed) && !isUsersDocument(parsed) && !isLayoutsDocument(parsed) && !isConfigurationDocument(parsed)) {
863
+ throw new Error(`Referenced document at ${item.$ref} is not a valid document type (profile, users, layouts, or configuration)`);
721
864
  }
722
865
  doc = parsed;
723
866
  if (item.$merge) {
724
867
  doc = applyMergeOverrides(doc, item.$merge);
725
868
  }
726
- } else if (isProfileDocument(item) || isUsersDocument(item) || isLayoutsDocument(item)) {
869
+ } else if (isProfileDocument(item) || isUsersDocument(item) || isLayoutsDocument(item) || isConfigurationDocument(item)) {
727
870
  doc = item;
728
871
  } else {
729
872
  continue;
@@ -734,6 +877,8 @@ async function resolveBundle(bundle, basePath) {
734
877
  result.users = mergeUsers(result.users, doc.payload ?? [], strategy.users);
735
878
  } else if (isLayoutsDocument(doc)) {
736
879
  result.layouts = mergeLayouts(result.layouts, doc.payload ?? [], strategy.layouts);
880
+ } else if (isConfigurationDocument(doc)) {
881
+ result.configuration = mergeConfiguration(result.configuration, doc.payload ?? []);
737
882
  }
738
883
  }
739
884
  return result;
@@ -786,6 +931,13 @@ async function compileBundleDocument(bundle, basePath) {
786
931
  payloads.push(compileUsersDocument(usersDoc));
787
932
  }
788
933
  }
934
+ if (resolved.configuration.length > 0) {
935
+ const configDoc = {
936
+ type: "configuration",
937
+ payload: resolved.configuration
938
+ };
939
+ payloads.push(compileConfigurationDocument(configDoc));
940
+ }
789
941
  return {
790
942
  id: "bundle",
791
943
  payloads
@@ -800,7 +952,8 @@ function compileBundleDocumentSync(bundle) {
800
952
  const result = {
801
953
  profiles: [],
802
954
  users: [],
803
- layouts: []
955
+ layouts: [],
956
+ configuration: []
804
957
  };
805
958
  const strategy = bundle.mergeStrategy ?? {};
806
959
  for (const item of bundle.documents) {
@@ -810,6 +963,8 @@ function compileBundleDocumentSync(bundle) {
810
963
  result.users = mergeUsers(result.users, item.payload ?? [], strategy.users);
811
964
  } else if (isLayoutsDocument(item)) {
812
965
  result.layouts = mergeLayouts(result.layouts, item.payload ?? [], strategy.layouts);
966
+ } else if (isConfigurationDocument(item)) {
967
+ result.configuration = mergeConfiguration(result.configuration, item.payload ?? []);
813
968
  }
814
969
  }
815
970
  const payloads = [];
@@ -841,6 +996,9 @@ function compileBundleDocumentSync(bundle) {
841
996
  payloads.push(compileUsersDocument({ type: "users", payload: result.users }));
842
997
  }
843
998
  }
999
+ if (result.configuration.length > 0) {
1000
+ payloads.push(compileConfigurationDocument({ type: "configuration", payload: result.configuration }));
1001
+ }
844
1002
  return {
845
1003
  id: "bundle",
846
1004
  payloads
@@ -851,12 +1009,14 @@ export {
851
1009
  isProfileDocument,
852
1010
  isUsersDocument,
853
1011
  isLayoutsDocument,
1012
+ isConfigurationDocument,
854
1013
  isBundleDocument,
855
1014
  isDocumentReference,
856
1015
  detectDocumentType,
857
1016
  compileProfileDocument,
858
1017
  compileUsersDocument,
859
1018
  compileLayoutsDocument,
1019
+ compileConfigurationDocument,
860
1020
  resolveBundle,
861
1021
  compileBundleDocument,
862
1022
  compileBundleDocumentSync
package/dist/index.js CHANGED
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ compileConfigurationDocument,
3
4
  compileLayoutsDocument,
4
5
  compileProfileDocument,
5
6
  compileUsersDocument,
6
7
  detectDocumentType,
7
8
  isBundleDocument,
9
+ isConfigurationDocument,
8
10
  isDocumentReference,
9
11
  isLayoutsDocument,
10
12
  isProfileDocument,
11
13
  isUsersDocument
12
- } from "./chunk-VHT6HO3N.js";
14
+ } from "./chunk-3PMKH6IT.js";
13
15
 
14
16
  // src/index.ts
15
17
  import { Command as Command4 } from "commander";
@@ -172,7 +174,8 @@ function compileToApiPayload(doc) {
172
174
  profiles: [],
173
175
  layouts: [],
174
176
  profileLayouts: [],
175
- users: []
177
+ users: [],
178
+ configuration: []
176
179
  };
177
180
  if (isProfileDocument(doc)) {
178
181
  const compiled = compileProfileDocument(doc);
@@ -191,6 +194,11 @@ function compileToApiPayload(doc) {
191
194
  result.layouts = compiled.payload.layouts;
192
195
  result.owner = compiled.payload.owner;
193
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;
194
202
  } else if (isBundleDocument(doc)) {
195
203
  const bundle = doc;
196
204
  for (const item of bundle.documents) {
@@ -208,12 +216,15 @@ function compileToApiPayload(doc) {
208
216
  } else if (isLayoutsDocument(item)) {
209
217
  const compiled = compileLayoutsDocument(item);
210
218
  result.layouts.push(...compiled.payload.layouts);
219
+ } else if (isConfigurationDocument(item)) {
220
+ const compiled = compileConfigurationDocument(item);
221
+ result.configuration.push(...compiled.payload.configuration);
211
222
  }
212
223
  }
213
224
  result.owner = bundle.owner;
214
225
  result.notificationEmail = bundle.notificationEmail;
215
226
  } else {
216
- throw new Error("Unknown document type. Expected profile, users, layouts, or bundle at root.");
227
+ throw new Error("Unknown document type. Expected profile, users, layouts, configuration, or bundle at root.");
217
228
  }
218
229
  return result;
219
230
  }
package/package.json CHANGED
@@ -1,53 +1,54 @@
1
- {
2
- "name": "@dimescheduler/setup",
3
- "version": "0.1.3",
4
- "description": "CLI tool to validate, compile, and deploy Dime.Scheduler configurations",
5
- "type": "module",
6
- "bin": {
7
- "dimescheduler-setup": "./dist/index.js"
8
- },
9
- "main": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
11
- "files": [
12
- "dist",
13
- "README.md"
14
- ],
15
- "scripts": {
16
- "build": "tsup src/index.ts --format esm --dts --clean",
17
- "watch": "tsup src/index.ts --format esm --watch",
18
- "start": "node dist/index.js",
19
- "lint": "eslint src/",
20
- "typecheck": "tsc --noEmit",
21
- "test": "vitest",
22
- "test:run": "vitest run"
23
- },
24
- "dependencies": {
25
- "commander": "^12.1.0",
26
- "json5": "^2.2.3",
27
- "picocolors": "^1.1.1"
28
- },
29
- "devDependencies": {
30
- "@types/node": "^22.10.0",
31
- "tsup": "^8.3.5",
32
- "typescript": "^5.7.2",
33
- "vitest": "^3.2.4"
34
- },
35
- "engines": {
36
- "node": ">=18"
37
- },
38
- "repository": {
39
- "type": "git",
40
- "url": "https://github.com/dimescheduler/dsl.git",
41
- "directory": "packages/cli"
42
- },
43
- "keywords": [
44
- "dimescheduler",
45
- "business-central",
46
- "businesscentral",
47
- "planning",
48
- "erp",
49
- "scheduling"
50
- ],
51
- "author": "Dime Software",
52
- "license": "MIT"
53
- }
1
+ {
2
+ "name": "@dimescheduler/setup",
3
+ "version": "0.11.4",
4
+ "description": "CLI tool to validate, compile, and deploy Dime.Scheduler configurations",
5
+ "type": "module",
6
+ "bin": {
7
+ "dimescheduler-setup": "./dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsup src/index.ts --format esm --dts --clean",
17
+ "watch": "tsup src/index.ts --format esm --watch",
18
+ "start": "node dist/index.js",
19
+ "lint": "eslint src/",
20
+ "typecheck": "tsc --noEmit",
21
+ "pretest": "npm run build",
22
+ "test": "vitest",
23
+ "test:run": "npm run build && vitest run"
24
+ },
25
+ "dependencies": {
26
+ "commander": "^12.1.0",
27
+ "json5": "^2.2.3",
28
+ "picocolors": "^1.1.1"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^22.10.0",
32
+ "tsup": "^8.3.5",
33
+ "typescript": "^5.7.2",
34
+ "vitest": "^3.2.4"
35
+ },
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/dimescheduler/dsl.git",
42
+ "directory": "packages/cli"
43
+ },
44
+ "keywords": [
45
+ "dimescheduler",
46
+ "business-central",
47
+ "businesscentral",
48
+ "planning",
49
+ "erp",
50
+ "scheduling"
51
+ ],
52
+ "author": "Dime Software",
53
+ "license": "MIT"
54
+ }