@fleetkeep/cli 0.5.0 → 0.6.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/README.md CHANGED
@@ -39,6 +39,39 @@ not enter them again. Account JSON exports include jobs, journeys and additional
39
39
  Xero authorisation and bill review take place in the web portal. Saved SHVL grants and
40
40
  credentials are not transferred between products or customer workspaces.
41
41
 
42
+ ## Service intervals and equipment
43
+
44
+ Set one service interval in days, weeks or months. The vehicle command clears the
45
+ alternative unit when switching, and converts weeks to days:
46
+
47
+ ```sh
48
+ fleetkeep vehicles update <vehicle-id> --service-interval-weeks 6
49
+ fleetkeep vehicles update <vehicle-id> --service-interval-months 12
50
+ fleetkeep vehicles update <vehicle-id> --clear serviceIntervalDays,serviceIntervalMonths
51
+ fleetkeep api call getWalkaroundSummary
52
+ fleetkeep api call listVehicleEquipment --path id=<vehicle-id>
53
+ fleetkeep api call updateVehicleEquipment --path id=<vehicle-id> --data-file equipment.json
54
+ ```
55
+
56
+ The walkaround summary returns vehicles checked today in London time, not a
57
+ roadworthiness certificate. Equipment payloads support `presetKey`, provider,
58
+ reference, cover dates, reminders and up to eight `details` label/value pairs.
59
+ Use an `Arrangement` detail for the confirmed ownership type, such as `Hired`.
60
+ Omitting details preserves existing values; an empty array explicitly clears them.
61
+ Use `previewEquipmentTemplate` before `applyEquipmentTemplate` for fleet-wide setup.
62
+
63
+ With the matching API update deployed, `createMaintenance` also accepts
64
+ `forecastConsent: true` and a `forecast` object containing `baselineDate`,
65
+ `baselineMileage`, `intervalMiles`, `annualMileage` and `reminderDays` (0 means on
66
+ the estimated date). Supply the actual last check, not an assumed MOT check date.
67
+ Duplicate setup does not create another reminder; refresh the maintenance list.
68
+ `completeMaintenance` accepts `completedDate` and `completedMileage` for
69
+ an existing forecast. Supply the identical body for preview and confirmation;
70
+ the next cycle retains the saved mileage interval and reminder timing. Ordinary
71
+ maintenance updates cannot edit calculated forecast dates. There are no automatic
72
+ fuel-card feeds in the CLI. Wex credentials and Xero authorisation are entered in
73
+ the website, never through CLI command arguments.
74
+
42
75
  ## Safety model
43
76
 
44
77
  - `api operations` is generated as a fixed allowlist of the published OpenAPI operation IDs.
package/api-command.mjs CHANGED
@@ -97,6 +97,9 @@ function operationPath(operation, assignments) {
97
97
  if (!values.has(name) || values.get(name) === '') {
98
98
  throw new Error(`${operation.id} requires --path ${name}=<value>.`);
99
99
  }
100
+ if (values.get(name) === '.' || values.get(name) === '..') {
101
+ throw new Error(`--path ${name} must not be a dot segment.`);
102
+ }
100
103
  path = path.replace(`{${name}}`, encodeURIComponent(values.get(name)));
101
104
  }
102
105
  return path;
@@ -280,9 +283,9 @@ export async function runApiCommand(args) {
280
283
  throw new Error('Use `fleetkeep api operations` or `fleetkeep api call`.');
281
284
  const operationId = args[1];
282
285
  if (!operationId || operationId.startsWith('--')) throw new Error('An operation ID is required.');
283
- const operation = operations[operationId];
284
- if (!operation) {
286
+ if (!Object.hasOwn(operations, operationId)) {
285
287
  throw new Error(`Unknown or unpublished Fleetkeep operation: ${operationId}.`);
286
288
  }
289
+ const operation = operations[operationId];
287
290
  await callOperation(operation, args.slice(2));
288
291
  }
package/fleetkeep.mjs CHANGED
@@ -56,6 +56,8 @@ Vehicle options:
56
56
  --last-service-date <YYYY-MM-DD>
57
57
  --last-service-mileage <integer>
58
58
  --service-interval-months <integer>
59
+ --service-interval-days <integer>
60
+ --service-interval-weeks <integer>
59
61
  --operational-status <active|standby|in_maintenance|off_road|sold_or_removed>
60
62
  --assigned-driver-name <text>
61
63
  --assigned-driver-contact <text>
@@ -63,7 +65,10 @@ Vehicle options:
63
65
 
64
66
  Clearable update fields:
65
67
  label, insuranceDueDate, lastServiceDate, lastServiceMileage, serviceIntervalMonths,
66
- assignedDriverName, assignedDriverContact, statusNotes
68
+ serviceIntervalDays, assignedDriverName, assignedDriverContact, statusNotes
69
+
70
+ Choose one service interval unit. Weeks are stored as days. Setting an interval
71
+ clears the alternative unit so an old interval cannot override the new one.
67
72
 
68
73
  Environment:
69
74
  FLEETKEEP_ACCESS_TOKEN Optional OAuth token override for automation
@@ -112,6 +117,11 @@ const VEHICLE_OPTIONS = new Map([
112
117
  '--service-interval-months',
113
118
  { field: 'serviceIntervalMonths', type: 'integer', min: 1, max: 120 }
114
119
  ],
120
+ ['--service-interval-days', { field: 'serviceIntervalDays', type: 'integer', min: 1, max: 3650 }],
121
+ [
122
+ '--service-interval-weeks',
123
+ { field: 'serviceIntervalDays', type: 'integer', min: 1, max: 521, multiplier: 7 }
124
+ ],
115
125
  ['--operational-status', { field: 'operationalStatus', type: 'status' }],
116
126
  ['--assigned-driver-name', { field: 'assignedDriverName', type: 'string' }],
117
127
  ['--assigned-driver-contact', { field: 'assignedDriverContact', type: 'string' }],
@@ -160,11 +170,22 @@ function parseVehicleValue(name, value, config) {
160
170
 
161
171
  function vehicleBody(args, { allowClear = false } = {}) {
162
172
  const body = {};
173
+ const intervalOptions = [
174
+ '--service-interval-days',
175
+ '--service-interval-weeks',
176
+ '--service-interval-months'
177
+ ];
178
+ if (intervalOptions.filter((name) => args.includes(name)).length > 1) {
179
+ throw new Error('Choose one service interval unit: days, weeks or months.');
180
+ }
163
181
  const recognised = new Set(['--json']);
164
182
  for (const [name, config] of VEHICLE_OPTIONS) {
165
183
  recognised.add(name);
166
184
  const value = requiredValue(args, name);
167
- if (value !== null) body[config.field] = parseVehicleValue(name, value, config);
185
+ if (value !== null) {
186
+ const parsed = parseVehicleValue(name, value, config);
187
+ body[config.field] = config.multiplier ? parsed * config.multiplier : parsed;
188
+ }
168
189
  }
169
190
 
170
191
  if (allowClear) {
@@ -189,6 +210,8 @@ function vehicleBody(args, { allowClear = false } = {}) {
189
210
  for (const arg of args) {
190
211
  if (arg.startsWith('--') && !recognised.has(arg)) throw new Error(`Unknown option: ${arg}.`);
191
212
  }
213
+ if (body.serviceIntervalDays != null) body.serviceIntervalMonths = null;
214
+ if (body.serviceIntervalMonths != null) body.serviceIntervalDays = null;
192
215
  return body;
193
216
  }
194
217
 
package/operations.mjs CHANGED
@@ -34,6 +34,7 @@ const definitions = [
34
34
  ['previewVehicleImport', 'POST', '/api/v1/imports/vehicles/preview', 'vehicles:read'],
35
35
  ['applyVehicleImport', 'POST', '/api/v1/imports/vehicles/apply', 'vehicles:write'],
36
36
  ['getWalkaroundDefinition', 'GET', '/api/v1/operations/walkaround-definition', 'operations:read'],
37
+ ['getWalkaroundSummary', 'GET', '/api/v1/operations/walkaround-summary', 'operations:read'],
37
38
  [
38
39
  'listWalkarounds',
39
40
  'GET',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetkeep/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Operate every published Fleetkeep API workflow with guarded writes and machine-readable output",
5
5
  "type": "module",
6
6
  "bin": {