@prismatic-io/components-jamf 0.0.0-stage → 0.0.1
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 +64 -2
- package/dist/icon.png +0 -0
- package/dist/index.js +220 -0
- package/npm-dist/icon.png +0 -0
- package/npm-dist/index.cjs +2885 -0
- package/npm-dist/index.d.cts +2263 -0
- package/package.json +51 -4
|
@@ -0,0 +1,2885 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
let _prismatic_io_spectral = require("@prismatic-io/spectral");
|
|
14
|
+
let _prismatic_io_spectral_http = require("@prismatic-io/spectral/http");
|
|
15
|
+
let node_crypto = require("node:crypto");
|
|
16
|
+
//#region src/connections/jamfBearerToken.ts
|
|
17
|
+
const jamfBearerToken = (0, _prismatic_io_spectral.connection)({
|
|
18
|
+
key: "jamfBearerToken",
|
|
19
|
+
display: {
|
|
20
|
+
label: "Basic Authentication",
|
|
21
|
+
description: "Authenticate using username and password."
|
|
22
|
+
},
|
|
23
|
+
inputs: {
|
|
24
|
+
baseUrl: (0, _prismatic_io_spectral.input)({
|
|
25
|
+
label: "Jamf Pro URL",
|
|
26
|
+
type: "string",
|
|
27
|
+
required: true,
|
|
28
|
+
shown: true,
|
|
29
|
+
comments: "The base URL of the Jamf Pro instance (e.g., https://acme.jamfcloud.com).",
|
|
30
|
+
placeholder: "Enter Jamf Pro URL (e.g., https://acme.jamfcloud.com)",
|
|
31
|
+
example: "https://acme.jamfcloud.com"
|
|
32
|
+
}),
|
|
33
|
+
username: (0, _prismatic_io_spectral.input)({
|
|
34
|
+
label: "Username",
|
|
35
|
+
type: "string",
|
|
36
|
+
required: true,
|
|
37
|
+
shown: true,
|
|
38
|
+
comments: "The Jamf Pro user account username. SSO accounts cannot be used for API authentication.",
|
|
39
|
+
placeholder: "Enter Jamf Pro username",
|
|
40
|
+
example: "admin"
|
|
41
|
+
}),
|
|
42
|
+
password: (0, _prismatic_io_spectral.input)({
|
|
43
|
+
label: "Password",
|
|
44
|
+
type: "password",
|
|
45
|
+
required: true,
|
|
46
|
+
shown: true,
|
|
47
|
+
comments: "The Jamf Pro user account password."
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/connections/jamfClientCredentials.ts
|
|
53
|
+
const jamfClientCredentials = (0, _prismatic_io_spectral.connection)({
|
|
54
|
+
key: "jamfClientCredentials",
|
|
55
|
+
display: {
|
|
56
|
+
label: "OAuth 2.0 Client Credentials",
|
|
57
|
+
description: "Authenticate using OAuth 2.0 client credentials."
|
|
58
|
+
},
|
|
59
|
+
inputs: {
|
|
60
|
+
baseUrl: (0, _prismatic_io_spectral.input)({
|
|
61
|
+
label: "Jamf Pro URL",
|
|
62
|
+
type: "string",
|
|
63
|
+
required: true,
|
|
64
|
+
shown: true,
|
|
65
|
+
comments: "The base URL of the Jamf Pro instance (e.g., https://acme.jamfcloud.com).",
|
|
66
|
+
placeholder: "Enter Jamf Pro URL (e.g., https://acme.jamfcloud.com)",
|
|
67
|
+
example: "https://acme.jamfcloud.com"
|
|
68
|
+
}),
|
|
69
|
+
clientId: (0, _prismatic_io_spectral.input)({
|
|
70
|
+
label: "Client ID",
|
|
71
|
+
type: "string",
|
|
72
|
+
required: true,
|
|
73
|
+
shown: true,
|
|
74
|
+
comments: "The API Client ID from Settings > API Roles and Clients in Jamf Pro.",
|
|
75
|
+
placeholder: "Enter API Client ID",
|
|
76
|
+
example: "abc12345-1234-1234-1234-abc1234567890"
|
|
77
|
+
}),
|
|
78
|
+
clientSecret: (0, _prismatic_io_spectral.input)({
|
|
79
|
+
label: "Client Secret",
|
|
80
|
+
type: "password",
|
|
81
|
+
required: true,
|
|
82
|
+
shown: true,
|
|
83
|
+
comments: "The API Client Secret from Settings > API Roles and Clients in Jamf Pro."
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
//#endregion
|
|
88
|
+
//#region src/connections/index.ts
|
|
89
|
+
var connections_default = [jamfClientCredentials, jamfBearerToken];
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/client.ts
|
|
92
|
+
const fetchAccessToken = async (connection, baseUrl) => {
|
|
93
|
+
if (connection.key === jamfClientCredentials.key) {
|
|
94
|
+
const clientId = _prismatic_io_spectral.util.types.toString(connection.fields.clientId);
|
|
95
|
+
const clientSecret = _prismatic_io_spectral.util.types.toString(connection.fields.clientSecret);
|
|
96
|
+
return (await (0, _prismatic_io_spectral_http.createClient)({ baseUrl }).post("/api/v1/oauth/token", new URLSearchParams({
|
|
97
|
+
grant_type: "client_credentials",
|
|
98
|
+
client_id: clientId,
|
|
99
|
+
client_secret: clientSecret
|
|
100
|
+
}).toString(), { headers: { "Content-Type": "application/x-www-form-urlencoded" } })).data.access_token;
|
|
101
|
+
}
|
|
102
|
+
if (connection.key === jamfBearerToken.key) {
|
|
103
|
+
const username = _prismatic_io_spectral.util.types.toString(connection.fields.username);
|
|
104
|
+
const password = _prismatic_io_spectral.util.types.toString(connection.fields.password);
|
|
105
|
+
return (await (0, _prismatic_io_spectral_http.createClient)({
|
|
106
|
+
baseUrl,
|
|
107
|
+
headers: { Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}` }
|
|
108
|
+
}).post("/api/v1/auth/token")).data.token;
|
|
109
|
+
}
|
|
110
|
+
throw new _prismatic_io_spectral.ConnectionError(connection, `Unsupported connection type: ${connection.key}`);
|
|
111
|
+
};
|
|
112
|
+
const getBaseUrl = (connection) => _prismatic_io_spectral.util.types.toString(connection.fields.baseUrl).replace(/\/$/, "");
|
|
113
|
+
const createClient = async (connection, debug = false) => {
|
|
114
|
+
const baseUrl = getBaseUrl(connection);
|
|
115
|
+
const token = await fetchAccessToken(connection, baseUrl);
|
|
116
|
+
return (0, _prismatic_io_spectral_http.createClient)({
|
|
117
|
+
baseUrl: `${baseUrl}/api`,
|
|
118
|
+
headers: {
|
|
119
|
+
Authorization: `Bearer ${token}`,
|
|
120
|
+
"Content-Type": "application/json",
|
|
121
|
+
Accept: "application/json"
|
|
122
|
+
},
|
|
123
|
+
debug
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
const createClassicClient = async (connection, debug = false) => {
|
|
127
|
+
const baseUrl = getBaseUrl(connection);
|
|
128
|
+
const token = await fetchAccessToken(connection, baseUrl);
|
|
129
|
+
return (0, _prismatic_io_spectral_http.createClient)({
|
|
130
|
+
baseUrl: `${baseUrl}/JSSResource`,
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${token}`,
|
|
133
|
+
Accept: "application/json"
|
|
134
|
+
},
|
|
135
|
+
debug
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/examplePayloads/categories.ts
|
|
140
|
+
const getCategoryExamplePayload = { data: {
|
|
141
|
+
id: "7",
|
|
142
|
+
name: "Productivity Apps",
|
|
143
|
+
priority: 9
|
|
144
|
+
} };
|
|
145
|
+
const listCategoriesExamplePayload = { data: {
|
|
146
|
+
results: [getCategoryExamplePayload.data],
|
|
147
|
+
totalCount: 1
|
|
148
|
+
} };
|
|
149
|
+
const createCategoryExamplePayload = { data: {
|
|
150
|
+
id: "8",
|
|
151
|
+
href: "https://your-instance.jamfcloud.com/api/v1/categories/8"
|
|
152
|
+
} };
|
|
153
|
+
const updateCategoryExamplePayload = { data: {
|
|
154
|
+
id: "7",
|
|
155
|
+
name: "Productivity Apps",
|
|
156
|
+
priority: 9
|
|
157
|
+
} };
|
|
158
|
+
const deleteCategoryExamplePayload = { data: "Successfully deleted category 7" };
|
|
159
|
+
const selectCategoryExamplePayload = { result: [{
|
|
160
|
+
key: "7",
|
|
161
|
+
label: "Productivity Apps"
|
|
162
|
+
}] };
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/examplePayloads/computers.ts
|
|
165
|
+
const getComputerExamplePayload = { data: {
|
|
166
|
+
id: "1",
|
|
167
|
+
udid: "A8C5F29D-1234-5678-ABCD-9E0F1B2C3D4E",
|
|
168
|
+
general: {
|
|
169
|
+
name: "MacBook-Pro-001",
|
|
170
|
+
lastContactTime: "2026-04-15T10:23:00.000Z",
|
|
171
|
+
platform: "Mac",
|
|
172
|
+
assetTag: null,
|
|
173
|
+
reportDate: "2026-04-15T10:22:00.000Z",
|
|
174
|
+
remoteManagement: { managed: true },
|
|
175
|
+
supervised: true
|
|
176
|
+
},
|
|
177
|
+
hardware: {
|
|
178
|
+
make: "Apple",
|
|
179
|
+
model: "MacBook Pro (16-inch, 2023)",
|
|
180
|
+
serialNumber: "C02XY1234567",
|
|
181
|
+
processorType: "Apple M2 Pro",
|
|
182
|
+
totalRamMegabytes: 16384
|
|
183
|
+
},
|
|
184
|
+
operatingSystem: {
|
|
185
|
+
name: "macOS",
|
|
186
|
+
version: "15.4.0",
|
|
187
|
+
build: "24E248"
|
|
188
|
+
},
|
|
189
|
+
userAndLocation: {
|
|
190
|
+
username: "jdoe",
|
|
191
|
+
realname: "Jane Doe",
|
|
192
|
+
email: "jdoe@example.com",
|
|
193
|
+
department: "Engineering",
|
|
194
|
+
building: null
|
|
195
|
+
},
|
|
196
|
+
security: {
|
|
197
|
+
sipStatus: "ENABLED",
|
|
198
|
+
gatekeeperStatus: "APP_STORE_AND_IDENTIFIED_DEVELOPERS",
|
|
199
|
+
xprotectVersion: "2199",
|
|
200
|
+
firewall: true
|
|
201
|
+
}
|
|
202
|
+
} };
|
|
203
|
+
const listComputersExamplePayload = { data: {
|
|
204
|
+
results: [getComputerExamplePayload.data],
|
|
205
|
+
totalCount: 1
|
|
206
|
+
} };
|
|
207
|
+
const updateComputerExamplePayload = { data: "Successfully updated computer 1" };
|
|
208
|
+
const selectComputerExamplePayload = { result: [{
|
|
209
|
+
key: "1",
|
|
210
|
+
label: "MacBook-Pro-001"
|
|
211
|
+
}] };
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region src/examplePayloads/departments.ts
|
|
214
|
+
const getDepartmentExamplePayload = { data: {
|
|
215
|
+
id: "10",
|
|
216
|
+
name: "Information Technology"
|
|
217
|
+
} };
|
|
218
|
+
const listDepartmentsExamplePayload = { data: {
|
|
219
|
+
results: [getDepartmentExamplePayload.data],
|
|
220
|
+
totalCount: 1
|
|
221
|
+
} };
|
|
222
|
+
const createDepartmentExamplePayload = { data: {
|
|
223
|
+
id: "11",
|
|
224
|
+
href: "https://your-instance.jamfcloud.com/api/v1/departments/11"
|
|
225
|
+
} };
|
|
226
|
+
const updateDepartmentExamplePayload = { data: {
|
|
227
|
+
id: "10",
|
|
228
|
+
name: "Information Technology"
|
|
229
|
+
} };
|
|
230
|
+
const deleteDepartmentExamplePayload = { data: "Successfully deleted department 10" };
|
|
231
|
+
const selectDepartmentExamplePayload = { result: [{
|
|
232
|
+
key: "10",
|
|
233
|
+
label: "Information Technology"
|
|
234
|
+
}] };
|
|
235
|
+
const getMobileDeviceExamplePayload = { data: {
|
|
236
|
+
id: "5",
|
|
237
|
+
managementId: "mgmt-abc-123",
|
|
238
|
+
name: "iPad-001",
|
|
239
|
+
udid: "B3D6E19F-4321-8765-DCBA-EF0A1B2C3D4E",
|
|
240
|
+
serialNumber: "DMPC123456789",
|
|
241
|
+
wifiMacAddress: "a4:5e:60:ab:cd:ef",
|
|
242
|
+
phoneNumber: null,
|
|
243
|
+
username: "jdoe",
|
|
244
|
+
type: "ios",
|
|
245
|
+
model: "iPad Pro (11-inch) (4th generation)",
|
|
246
|
+
modelIdentifier: "iPad14,3",
|
|
247
|
+
softwareUpdateDeviceId: null,
|
|
248
|
+
osVersion: "17.4",
|
|
249
|
+
osType: "iOS",
|
|
250
|
+
realname: "Jane Doe",
|
|
251
|
+
email: "jdoe@example.com",
|
|
252
|
+
department: "Engineering"
|
|
253
|
+
} };
|
|
254
|
+
const listMobileDevicesExamplePayload = { data: {
|
|
255
|
+
results: [{
|
|
256
|
+
mobileDeviceId: "5",
|
|
257
|
+
deviceType: "iOS",
|
|
258
|
+
general: {
|
|
259
|
+
udid: "B3D6E19F-4321-8765-DCBA-EF0A1B2C3D4E",
|
|
260
|
+
displayName: "iPad-001",
|
|
261
|
+
assetTag: "304822",
|
|
262
|
+
siteId: "1",
|
|
263
|
+
lastInventoryUpdateDate: "2026-06-14T18:22:05.000Z",
|
|
264
|
+
osVersion: "17.4",
|
|
265
|
+
osRapidSecurityResponse: "(a)",
|
|
266
|
+
osBuild: "21E219",
|
|
267
|
+
osSupplementalBuildVersion: "21E220",
|
|
268
|
+
softwareUpdateDeviceId: "J617AP",
|
|
269
|
+
ipAddress: "10.0.12.45",
|
|
270
|
+
managed: true,
|
|
271
|
+
supervised: true,
|
|
272
|
+
deviceOwnershipType: "Institutional",
|
|
273
|
+
enrollmentMethodPrestage: "PreStage enrollment",
|
|
274
|
+
enrollmentSessionTokenValid: true,
|
|
275
|
+
lastEnrolledDate: "2026-01-05T09:14:00.000Z",
|
|
276
|
+
mdmProfileExpirationDate: "2027-01-05T09:14:00.000Z",
|
|
277
|
+
timeZone: "America/Chicago",
|
|
278
|
+
declarativeDeviceManagementEnabled: true,
|
|
279
|
+
managementId: "mgmt-abc-123",
|
|
280
|
+
extensionAttributes: [],
|
|
281
|
+
lastLoggedInUsernameSelfService: null,
|
|
282
|
+
lastLoggedInUsernameSelfServiceTimestamp: null,
|
|
283
|
+
sharedIpad: false,
|
|
284
|
+
diagnosticAndUsageReportingEnabled: false,
|
|
285
|
+
appAnalyticsEnabled: false,
|
|
286
|
+
residentUsers: null,
|
|
287
|
+
quotaSize: null,
|
|
288
|
+
temporarySessionOnly: null,
|
|
289
|
+
temporarySessionTimeout: null,
|
|
290
|
+
userSessionTimeout: null,
|
|
291
|
+
syncedToComputer: -1,
|
|
292
|
+
maximumSharediPadUsersStored: -1,
|
|
293
|
+
lastBackupDate: "2026-06-10T03:00:00.000Z",
|
|
294
|
+
deviceLocatorServiceEnabled: false,
|
|
295
|
+
doNotDisturbEnabled: false,
|
|
296
|
+
cloudBackupEnabled: true,
|
|
297
|
+
lastCloudBackupDate: "2026-06-13T03:11:00.000Z",
|
|
298
|
+
locationServicesForSelfServiceMobileEnabled: false,
|
|
299
|
+
itunesStoreAccountActive: false,
|
|
300
|
+
exchangeDeviceId: "",
|
|
301
|
+
tethered: false
|
|
302
|
+
},
|
|
303
|
+
hardware: {
|
|
304
|
+
capacityMb: 256e3,
|
|
305
|
+
availableSpaceMb: 198450,
|
|
306
|
+
usedSpacePercentage: 22,
|
|
307
|
+
batteryLevel: 87,
|
|
308
|
+
serialNumber: "DMPC123456789",
|
|
309
|
+
wifiMacAddress: "a4:5e:60:ab:cd:ef",
|
|
310
|
+
bluetoothMacAddress: "a4:5e:60:ab:cd:f0",
|
|
311
|
+
modelIdentifier: "iPad14,3",
|
|
312
|
+
model: "iPad Pro (11-inch) (4th generation)",
|
|
313
|
+
modelNumber: "MNXE3LL/A",
|
|
314
|
+
bluetoothLowEnergyCapable: true,
|
|
315
|
+
deviceId: "J617AP"
|
|
316
|
+
},
|
|
317
|
+
userAndLocation: {
|
|
318
|
+
username: "jdoe",
|
|
319
|
+
realName: "Jane Doe",
|
|
320
|
+
emailAddress: "jdoe@example.com",
|
|
321
|
+
position: "Field Technician",
|
|
322
|
+
phoneNumber: "555-0142",
|
|
323
|
+
departmentId: "1",
|
|
324
|
+
buildingId: "1",
|
|
325
|
+
room: "204",
|
|
326
|
+
building: "Headquarters",
|
|
327
|
+
department: "Engineering"
|
|
328
|
+
},
|
|
329
|
+
security: {
|
|
330
|
+
dataProtected: true,
|
|
331
|
+
blockLevelEncryptionCapable: true,
|
|
332
|
+
fileLevelEncryptionCapable: true,
|
|
333
|
+
passcodePresent: true,
|
|
334
|
+
passcodeCompliant: true,
|
|
335
|
+
passcodeCompliantWithProfile: true,
|
|
336
|
+
hardwareEncryption: 3,
|
|
337
|
+
activationLockEnabled: true,
|
|
338
|
+
jailBreakDetected: false,
|
|
339
|
+
lostModeEnabled: false
|
|
340
|
+
}
|
|
341
|
+
}],
|
|
342
|
+
totalCount: 1
|
|
343
|
+
} };
|
|
344
|
+
const selectMobileDeviceExamplePayload = { result: [{
|
|
345
|
+
key: "5",
|
|
346
|
+
label: "iPad-001"
|
|
347
|
+
}] };
|
|
348
|
+
//#endregion
|
|
349
|
+
//#region src/examplePayloads/packages.ts
|
|
350
|
+
const packageExample = {
|
|
351
|
+
id: "20",
|
|
352
|
+
packageName: "Google Chrome 120.0",
|
|
353
|
+
fileName: "GoogleChrome-120.0.6099.199.pkg",
|
|
354
|
+
categoryId: "-1",
|
|
355
|
+
info: "Google Chrome browser installer.",
|
|
356
|
+
notes: "",
|
|
357
|
+
priority: 10,
|
|
358
|
+
osRequirements: "",
|
|
359
|
+
rebootRequired: false,
|
|
360
|
+
fillUserTemplate: false,
|
|
361
|
+
indexed: false,
|
|
362
|
+
fillExistingUsers: false,
|
|
363
|
+
swu: false,
|
|
364
|
+
selfHealNotify: false,
|
|
365
|
+
selfHealingAction: "nothing",
|
|
366
|
+
osInstall: false,
|
|
367
|
+
serialNumber: "",
|
|
368
|
+
parentPackageId: "-1",
|
|
369
|
+
basePath: "",
|
|
370
|
+
suppressUpdates: false,
|
|
371
|
+
cloudTransferStatus: "",
|
|
372
|
+
ignoreConflicts: false,
|
|
373
|
+
suppressFromDock: false,
|
|
374
|
+
suppressEula: false,
|
|
375
|
+
suppressRegistration: false,
|
|
376
|
+
installLanguage: "en_US",
|
|
377
|
+
md5: "",
|
|
378
|
+
sha256: "",
|
|
379
|
+
hashType: "SHA_512",
|
|
380
|
+
hashValue: "",
|
|
381
|
+
size: "",
|
|
382
|
+
osInstallerVersion: "",
|
|
383
|
+
manifest: "",
|
|
384
|
+
manifestFileName: "",
|
|
385
|
+
format: "",
|
|
386
|
+
sha3512: ""
|
|
387
|
+
};
|
|
388
|
+
const getPackageExamplePayload = { data: packageExample };
|
|
389
|
+
const listPackagesExamplePayload = { data: {
|
|
390
|
+
results: [packageExample],
|
|
391
|
+
totalCount: 1
|
|
392
|
+
} };
|
|
393
|
+
const createPackageExamplePayload = { data: {
|
|
394
|
+
id: "21",
|
|
395
|
+
href: "https://your-instance.jamfcloud.com/api/v1/packages/21"
|
|
396
|
+
} };
|
|
397
|
+
const updatePackageExamplePayload = { data: packageExample };
|
|
398
|
+
const deletePackageExamplePayload = { data: "Successfully deleted package 20" };
|
|
399
|
+
const selectPackageExamplePayload = { result: [{
|
|
400
|
+
key: "12",
|
|
401
|
+
label: "Google Chrome 120.0.pkg"
|
|
402
|
+
}] };
|
|
403
|
+
//#endregion
|
|
404
|
+
//#region src/examplePayloads/scripts.ts
|
|
405
|
+
const scriptExample = {
|
|
406
|
+
id: "12",
|
|
407
|
+
name: "Install Chrome",
|
|
408
|
+
categoryId: "3",
|
|
409
|
+
categoryName: "Browsers",
|
|
410
|
+
info: "Installs Google Chrome from the vendor CDN.",
|
|
411
|
+
notes: "",
|
|
412
|
+
priority: "AFTER",
|
|
413
|
+
parameter4: "",
|
|
414
|
+
parameter5: "",
|
|
415
|
+
parameter6: "",
|
|
416
|
+
parameter7: "",
|
|
417
|
+
parameter8: "",
|
|
418
|
+
parameter9: "",
|
|
419
|
+
parameter10: "",
|
|
420
|
+
parameter11: "",
|
|
421
|
+
osRequirements: "",
|
|
422
|
+
scriptContents: "#!/bin/bash\necho 'Installing Chrome'"
|
|
423
|
+
};
|
|
424
|
+
const getScriptExamplePayload = { data: scriptExample };
|
|
425
|
+
const listScriptsExamplePayload = { data: {
|
|
426
|
+
results: [scriptExample],
|
|
427
|
+
totalCount: 1
|
|
428
|
+
} };
|
|
429
|
+
const createScriptExamplePayload = { data: {
|
|
430
|
+
id: "13",
|
|
431
|
+
href: "https://your-instance.jamfcloud.com/api/v1/scripts/13"
|
|
432
|
+
} };
|
|
433
|
+
const updateScriptExamplePayload = { data: scriptExample };
|
|
434
|
+
const deleteScriptExamplePayload = { data: "Successfully deleted script 12" };
|
|
435
|
+
const selectScriptExamplePayload = { result: [{
|
|
436
|
+
key: "7",
|
|
437
|
+
label: "Install Chrome"
|
|
438
|
+
}] };
|
|
439
|
+
//#endregion
|
|
440
|
+
//#region src/examplePayloads/users.ts
|
|
441
|
+
const listUsersExamplePayload = { data: {
|
|
442
|
+
results: [{
|
|
443
|
+
id: "42",
|
|
444
|
+
username: "jdoe",
|
|
445
|
+
realname: "Jane Doe",
|
|
446
|
+
email: "jdoe@example.com",
|
|
447
|
+
position: "Software Engineer",
|
|
448
|
+
enableCustomPhotoUrl: false,
|
|
449
|
+
customPhotoUrl: null,
|
|
450
|
+
ldapServer: null,
|
|
451
|
+
extensionAttributes: []
|
|
452
|
+
}],
|
|
453
|
+
totalCount: 1,
|
|
454
|
+
page: 0,
|
|
455
|
+
pageSize: 100,
|
|
456
|
+
totalPages: 1,
|
|
457
|
+
hasNext: false,
|
|
458
|
+
hasPrevious: false
|
|
459
|
+
} };
|
|
460
|
+
//#endregion
|
|
461
|
+
//#region src/examplePayloads/webhook.ts
|
|
462
|
+
const webhookExamplePayload = { payload: {
|
|
463
|
+
headers: {
|
|
464
|
+
Accept: "text/plain, application/xml, text/xml, application/json, application/cbor, application/*+xml, application/*+json, */*",
|
|
465
|
+
"Content-Type": "application/json",
|
|
466
|
+
Host: "hooks.example.com",
|
|
467
|
+
"User-Agent": "Java/21.0.11",
|
|
468
|
+
"X-Jamf-Signature": "123456"
|
|
469
|
+
},
|
|
470
|
+
queryParameters: {},
|
|
471
|
+
rawBody: { data: "" },
|
|
472
|
+
body: {
|
|
473
|
+
data: {
|
|
474
|
+
webhook: {
|
|
475
|
+
id: 9,
|
|
476
|
+
name: "Header Auth",
|
|
477
|
+
webhookEvent: "ComputerAdded",
|
|
478
|
+
eventTimestamp: 1780529995879
|
|
479
|
+
},
|
|
480
|
+
event: {
|
|
481
|
+
udid: "45436edf-864e-4364-982a-330b01d39e28",
|
|
482
|
+
deviceName: "Boalime",
|
|
483
|
+
model: "13-inch MacBook Pro (Mid 2012)",
|
|
484
|
+
macAddress: "6A:2C:4B:B7:65:C8",
|
|
485
|
+
alternateMacAddress: "82:45:58:44:dc:07",
|
|
486
|
+
serialNumber: "C02ZC2QYLJHD",
|
|
487
|
+
osVersion: "10.9.5",
|
|
488
|
+
osBuild: "13A603",
|
|
489
|
+
userDirectoryID: "-1",
|
|
490
|
+
username: "Madison Anderson",
|
|
491
|
+
realName: "13-inch MacBook",
|
|
492
|
+
emailAddress: "email@com.pl",
|
|
493
|
+
phone: "123-456-789",
|
|
494
|
+
position: "IT Team Lead",
|
|
495
|
+
department: "",
|
|
496
|
+
building: "",
|
|
497
|
+
room: "5",
|
|
498
|
+
ipAddress: "247.185.82.186",
|
|
499
|
+
reportedIpV4Address: "247.185.82.186",
|
|
500
|
+
reportedIpV6Address: "",
|
|
501
|
+
jssID: 6,
|
|
502
|
+
managementId: "fd14f8f3-d5a4-4c44-ad7b-5f93d2ed15cb"
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
contentType: "application/json"
|
|
506
|
+
},
|
|
507
|
+
pathFragment: "",
|
|
508
|
+
webhookUrls: { Webhook: "https://hooks.example.com/trigger/abc123==" },
|
|
509
|
+
webhookApiKeys: { Webhook: ["sample-api-key"] },
|
|
510
|
+
invokeUrl: "https://hooks.example.com/trigger/abc123==",
|
|
511
|
+
executionId: "exec_789456",
|
|
512
|
+
customer: {
|
|
513
|
+
id: "cust_12345",
|
|
514
|
+
name: "Example Customer",
|
|
515
|
+
externalId: "ext_cust_98765"
|
|
516
|
+
},
|
|
517
|
+
instance: {
|
|
518
|
+
id: "inst_54321",
|
|
519
|
+
name: "Jamf - Webhook Integration"
|
|
520
|
+
},
|
|
521
|
+
user: {
|
|
522
|
+
id: "user_67890",
|
|
523
|
+
email: "admin@example.com",
|
|
524
|
+
name: "Admin User",
|
|
525
|
+
externalId: "ext_user_12345"
|
|
526
|
+
},
|
|
527
|
+
integration: {
|
|
528
|
+
id: "intg_98765",
|
|
529
|
+
name: "Jamf - Webhook Integration",
|
|
530
|
+
versionSequenceId: "v1.0.0",
|
|
531
|
+
externalVersion: "1.0.0"
|
|
532
|
+
},
|
|
533
|
+
flow: {
|
|
534
|
+
id: "flow_45678",
|
|
535
|
+
name: "Computer Inventory Completed Webhook",
|
|
536
|
+
stableId: "stable_flow_45678"
|
|
537
|
+
},
|
|
538
|
+
startedAt: "2026-04-15T10:23:00.000Z",
|
|
539
|
+
globalDebug: false
|
|
540
|
+
} };
|
|
541
|
+
const getWebhookExamplePayload = { data: { webhook: {
|
|
542
|
+
id: 1,
|
|
543
|
+
name: "New Computer Notifier",
|
|
544
|
+
enabled: true,
|
|
545
|
+
url: "https://example.com/webhook",
|
|
546
|
+
content_type: "application/json",
|
|
547
|
+
event: "ComputerAdded",
|
|
548
|
+
connection_timeout: 5,
|
|
549
|
+
read_timeout: 2,
|
|
550
|
+
authentication_type: "NONE"
|
|
551
|
+
} } };
|
|
552
|
+
const createWebhookExamplePayload = { data: { id: 1 } };
|
|
553
|
+
const updateWebhookExamplePayload = { data: { id: 1 } };
|
|
554
|
+
const listWebhooksExamplePayload = { data: { webhooks: [{
|
|
555
|
+
id: 1,
|
|
556
|
+
name: "New Computer Notifier"
|
|
557
|
+
}] } };
|
|
558
|
+
const deleteWebhookExamplePayload = { data: "Successfully deleted webhook 1" };
|
|
559
|
+
const deleteInstancedWebhooksExamplePayload = { data: { webhooksDeleted: 1 } };
|
|
560
|
+
const selectWebhookExamplePayload = { result: [{
|
|
561
|
+
key: "1",
|
|
562
|
+
label: "New Computer Notifier"
|
|
563
|
+
}] };
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/constants.ts
|
|
566
|
+
const MAX_PAGE_SIZE = 1e3;
|
|
567
|
+
const WATERMARK_SKEW_MARGIN_MS = 6e4;
|
|
568
|
+
const WEBHOOK_EVENTS = [
|
|
569
|
+
"ComputerAdded",
|
|
570
|
+
"ComputerCheckIn",
|
|
571
|
+
"ComputerInventoryCompleted",
|
|
572
|
+
"ComputerPatchPolicyCompleted",
|
|
573
|
+
"ComputerPolicyFinished",
|
|
574
|
+
"ComputerPushCapabilityChanged",
|
|
575
|
+
"MobileDeviceCheckIn",
|
|
576
|
+
"MobileDeviceCommandCompleted",
|
|
577
|
+
"MobileDeviceEnrolled",
|
|
578
|
+
"MobileDeviceInventoryCompleted",
|
|
579
|
+
"MobileDevicePushSent",
|
|
580
|
+
"MobileDeviceUnenrolled",
|
|
581
|
+
"JSSStartup",
|
|
582
|
+
"JSSShutdown",
|
|
583
|
+
"DeviceAddedToDEP",
|
|
584
|
+
"SmartGroupComputerMembershipChange",
|
|
585
|
+
"SmartGroupMobileDeviceMembershipChange",
|
|
586
|
+
"SmartGroupUserMembershipChange",
|
|
587
|
+
"PatchSoftwareTitleUpdated",
|
|
588
|
+
"PushSent",
|
|
589
|
+
"RestAPIOperation",
|
|
590
|
+
"SCEPChallenge"
|
|
591
|
+
];
|
|
592
|
+
const WEBHOOK_AUTH_HEADER = "X-Jamf-Signature";
|
|
593
|
+
const LOOK_BACK_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
594
|
+
//#endregion
|
|
595
|
+
//#region src/util/clean.ts
|
|
596
|
+
const toOptionalString = (value) => value ? _prismatic_io_spectral.util.types.toString(value) : void 0;
|
|
597
|
+
const toOptionalNumber = (value) => value ? _prismatic_io_spectral.util.types.toNumber(value) : void 0;
|
|
598
|
+
const toOptionalBool = (value) => value === void 0 || value === null || value === "" ? void 0 : _prismatic_io_spectral.util.types.toBool(value);
|
|
599
|
+
const asStringArray = (value) => value;
|
|
600
|
+
const lookBackDateClean = (value) => {
|
|
601
|
+
const raw = value ? _prismatic_io_spectral.util.types.toString(value).trim() : "";
|
|
602
|
+
if (!raw) return "";
|
|
603
|
+
const match = typeof value === "string" ? raw.match(LOOK_BACK_DATE_PATTERN) : null;
|
|
604
|
+
if (!match) throw new Error(`Look-back Date must be a date in YYYY-MM-DD format. Received: ${raw}`);
|
|
605
|
+
const [, yearStr, monthStr, dayStr] = match;
|
|
606
|
+
const year = _prismatic_io_spectral.util.types.toNumber(yearStr);
|
|
607
|
+
const month = _prismatic_io_spectral.util.types.toNumber(monthStr);
|
|
608
|
+
const day = _prismatic_io_spectral.util.types.toNumber(dayStr);
|
|
609
|
+
const parsed = new Date(Date.UTC(year, month - 1, day));
|
|
610
|
+
if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) throw new Error(`Look-back Date must be a date in YYYY-MM-DD format. Received: ${raw}`);
|
|
611
|
+
if (parsed.getTime() > Date.now()) throw new Error(`Look-back Date cannot be a future date. Received: ${raw}`);
|
|
612
|
+
return parsed.toISOString();
|
|
613
|
+
};
|
|
614
|
+
//#endregion
|
|
615
|
+
//#region src/util/sort.ts
|
|
616
|
+
const sortElementsByLabel = (a, b) => (a.label ?? "") < (b.label ?? "") ? -1 : 1;
|
|
617
|
+
//#endregion
|
|
618
|
+
//#region src/util/elements.ts
|
|
619
|
+
const selectValue = (item, selector) => typeof selector === "function" ? selector(item) : item[selector];
|
|
620
|
+
const mapToSortedElements = (items, keyAttr, labelAttr) => items.map((item) => {
|
|
621
|
+
const key = _prismatic_io_spectral.util.types.toString(selectValue(item, keyAttr));
|
|
622
|
+
return {
|
|
623
|
+
key,
|
|
624
|
+
label: _prismatic_io_spectral.util.types.toString(selectValue(item, labelAttr), key)
|
|
625
|
+
};
|
|
626
|
+
}).sort(sortElementsByLabel);
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region src/util/labels.ts
|
|
629
|
+
const humanizeEventLabel = (event) => event.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
|
|
630
|
+
const webhookEventOptions = WEBHOOK_EVENTS.map((event) => ({
|
|
631
|
+
label: humanizeEventLabel(event),
|
|
632
|
+
value: event
|
|
633
|
+
}));
|
|
634
|
+
//#endregion
|
|
635
|
+
//#region src/util/merge.ts
|
|
636
|
+
const mergeDefined = (existing, overrides) => ({
|
|
637
|
+
...existing,
|
|
638
|
+
...Object.fromEntries(Object.entries(overrides).filter(([, value]) => value !== void 0))
|
|
639
|
+
});
|
|
640
|
+
//#endregion
|
|
641
|
+
//#region src/util/pagination.ts
|
|
642
|
+
const paginateResults = async (client, endpoint, fetchAll, params) => {
|
|
643
|
+
const results = [];
|
|
644
|
+
let lastResponse = {};
|
|
645
|
+
let page = 0;
|
|
646
|
+
let hasMore = true;
|
|
647
|
+
while (hasMore) {
|
|
648
|
+
const { data } = await client.get(endpoint, {
|
|
649
|
+
params: fetchAll ? {
|
|
650
|
+
...params,
|
|
651
|
+
page,
|
|
652
|
+
"page-size": MAX_PAGE_SIZE
|
|
653
|
+
} : params,
|
|
654
|
+
paramsSerializer: { indexes: null }
|
|
655
|
+
});
|
|
656
|
+
lastResponse = data;
|
|
657
|
+
results.push(...data.results);
|
|
658
|
+
page += 1;
|
|
659
|
+
hasMore = fetchAll && data.results.length > 0 && results.length < data.totalCount;
|
|
660
|
+
}
|
|
661
|
+
return {
|
|
662
|
+
...lastResponse,
|
|
663
|
+
results
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
//#endregion
|
|
667
|
+
//#region src/util/polling.ts
|
|
668
|
+
const resolveNewComputerChanges = (data) => (data ?? []).map((record) => ({
|
|
669
|
+
changeType: "created",
|
|
670
|
+
record
|
|
671
|
+
}));
|
|
672
|
+
const SECOND_MS = 1e3;
|
|
673
|
+
const INVENTORY_ENDPOINT = "/v3/computers-inventory";
|
|
674
|
+
const TRIGGER_NAME = "pollNewComputers";
|
|
675
|
+
const NORMAL_SORT = "general.lastEnrolledDate:asc,id:asc";
|
|
676
|
+
const TIE_SORT = "id:asc";
|
|
677
|
+
const toIso = (epochMs) => new Date(epochMs).toISOString();
|
|
678
|
+
const truncateToSecond = (iso) => toIso(Math.floor(Date.parse(iso) / SECOND_MS) * SECOND_MS);
|
|
679
|
+
const toFilterDate = (iso) => iso.replace(/\.\d+Z$/, "Z");
|
|
680
|
+
const resolveSafeHorizon = (now) => truncateToSecond(toIso(Date.parse(now) - WATERMARK_SKEW_MARGIN_MS));
|
|
681
|
+
const fetchComputerPage = (client) => async ({ filter, sort, pageSize }) => {
|
|
682
|
+
const { data } = await client.get(INVENTORY_ENDPOINT, {
|
|
683
|
+
params: {
|
|
684
|
+
section: ["GENERAL"],
|
|
685
|
+
filter,
|
|
686
|
+
sort,
|
|
687
|
+
page: 0,
|
|
688
|
+
"page-size": pageSize
|
|
689
|
+
},
|
|
690
|
+
paramsSerializer: { indexes: null }
|
|
691
|
+
});
|
|
692
|
+
return data.results;
|
|
693
|
+
};
|
|
694
|
+
const enrolledSecond = (record) => {
|
|
695
|
+
const raw = record.general?.lastEnrolledDate;
|
|
696
|
+
const at = typeof raw === "string" ? Date.parse(raw) : NaN;
|
|
697
|
+
return Number.isNaN(at) ? null : Math.floor(at / SECOND_MS) * SECOND_MS;
|
|
698
|
+
};
|
|
699
|
+
const noProgress = (watermark) => /* @__PURE__ */ new Error(`${TRIGGER_NAME}: the watermark cursor cannot advance past ${watermark}: a full page (page size ${MAX_PAGE_SIZE}) held no computer enrolled at or after it, so the same request would return the same page on every poll. Stopping instead of looping.`);
|
|
700
|
+
const normalRound = async (fetchPage, cursor, horizon) => {
|
|
701
|
+
const watermarkMs = Date.parse(cursor.watermark);
|
|
702
|
+
if (watermarkMs > Date.parse(horizon)) return {
|
|
703
|
+
delivered: [],
|
|
704
|
+
cursor,
|
|
705
|
+
drained: true
|
|
706
|
+
};
|
|
707
|
+
const batch = await fetchPage({
|
|
708
|
+
filter: `general.lastEnrolledDate=ge="${toFilterDate(cursor.watermark)}";general.lastEnrolledDate=le="${toFilterDate(horizon)}"`,
|
|
709
|
+
sort: NORMAL_SORT,
|
|
710
|
+
pageSize: MAX_PAGE_SIZE
|
|
711
|
+
});
|
|
712
|
+
const boundary = new Set(cursor.boundaryIds);
|
|
713
|
+
const delivered = [];
|
|
714
|
+
let latestMs = watermarkMs;
|
|
715
|
+
let latestIds = [];
|
|
716
|
+
for (const record of batch) {
|
|
717
|
+
const at = enrolledSecond(record);
|
|
718
|
+
if (at === null) {
|
|
719
|
+
delivered.push(record);
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
if (at < watermarkMs) continue;
|
|
723
|
+
if (!(at === watermarkMs && boundary.has(record.id))) delivered.push(record);
|
|
724
|
+
if (at > latestMs) {
|
|
725
|
+
latestMs = at;
|
|
726
|
+
latestIds = [record.id];
|
|
727
|
+
} else if (at === latestMs) latestIds.push(record.id);
|
|
728
|
+
}
|
|
729
|
+
const full = batch.length >= MAX_PAGE_SIZE;
|
|
730
|
+
const stuck = latestMs === watermarkMs;
|
|
731
|
+
if (full && stuck && latestIds.length === 0) throw noProgress(cursor.watermark);
|
|
732
|
+
const next = stuck ? {
|
|
733
|
+
watermark: cursor.watermark,
|
|
734
|
+
boundaryIds: [.../* @__PURE__ */ new Set([...cursor.boundaryIds, ...latestIds])]
|
|
735
|
+
} : {
|
|
736
|
+
watermark: toIso(latestMs),
|
|
737
|
+
boundaryIds: latestIds
|
|
738
|
+
};
|
|
739
|
+
if (!full) return {
|
|
740
|
+
delivered,
|
|
741
|
+
cursor: next,
|
|
742
|
+
drained: true
|
|
743
|
+
};
|
|
744
|
+
return {
|
|
745
|
+
delivered,
|
|
746
|
+
cursor: stuck ? {
|
|
747
|
+
...next,
|
|
748
|
+
tieGroup: { lastKey: null }
|
|
749
|
+
} : next,
|
|
750
|
+
drained: false
|
|
751
|
+
};
|
|
752
|
+
};
|
|
753
|
+
const tieRound = async (fetchPage, cursor, horizon) => {
|
|
754
|
+
const watermarkMs = Date.parse(cursor.watermark);
|
|
755
|
+
const lastKey = cursor.tieGroup?.lastKey ?? null;
|
|
756
|
+
const batch = await fetchPage({
|
|
757
|
+
filter: `general.lastEnrolledDate=ge="${toFilterDate(cursor.watermark)}";general.lastEnrolledDate=lt="${toFilterDate(toIso(watermarkMs + SECOND_MS))}"${lastKey === null ? "" : `;id=gt=${lastKey}`}`,
|
|
758
|
+
sort: TIE_SORT,
|
|
759
|
+
pageSize: MAX_PAGE_SIZE
|
|
760
|
+
});
|
|
761
|
+
const boundary = new Set(cursor.boundaryIds);
|
|
762
|
+
const delivered = [];
|
|
763
|
+
for (const record of batch) {
|
|
764
|
+
if (enrolledSecond(record) !== watermarkMs || boundary.has(record.id)) continue;
|
|
765
|
+
delivered.push(record);
|
|
766
|
+
boundary.add(record.id);
|
|
767
|
+
}
|
|
768
|
+
if (batch.length >= 1e3) {
|
|
769
|
+
const nextKey = batch[batch.length - 1].id;
|
|
770
|
+
if (nextKey === lastKey) throw noProgress(cursor.watermark);
|
|
771
|
+
return {
|
|
772
|
+
delivered,
|
|
773
|
+
cursor: {
|
|
774
|
+
watermark: cursor.watermark,
|
|
775
|
+
boundaryIds: [...boundary],
|
|
776
|
+
tieGroup: { lastKey: nextKey }
|
|
777
|
+
},
|
|
778
|
+
drained: false
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
if (watermarkMs < Date.parse(horizon)) return {
|
|
782
|
+
delivered,
|
|
783
|
+
cursor: {
|
|
784
|
+
watermark: toIso(watermarkMs + SECOND_MS),
|
|
785
|
+
boundaryIds: []
|
|
786
|
+
},
|
|
787
|
+
drained: false
|
|
788
|
+
};
|
|
789
|
+
return {
|
|
790
|
+
delivered,
|
|
791
|
+
cursor: {
|
|
792
|
+
watermark: cursor.watermark,
|
|
793
|
+
boundaryIds: [...boundary]
|
|
794
|
+
},
|
|
795
|
+
drained: true
|
|
796
|
+
};
|
|
797
|
+
};
|
|
798
|
+
const drainWatermark = async (fetchPage, start, horizon, maxPages) => {
|
|
799
|
+
const delivered = [];
|
|
800
|
+
let cursor = start;
|
|
801
|
+
for (let page = 0; page < maxPages; page++) {
|
|
802
|
+
const round = cursor.tieGroup ? await tieRound(fetchPage, cursor, horizon) : await normalRound(fetchPage, cursor, horizon);
|
|
803
|
+
delivered.push(...round.delivered);
|
|
804
|
+
cursor = round.cursor;
|
|
805
|
+
if (round.drained) return {
|
|
806
|
+
delivered,
|
|
807
|
+
cursor,
|
|
808
|
+
drained: true
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
return {
|
|
812
|
+
delivered,
|
|
813
|
+
cursor,
|
|
814
|
+
drained: false
|
|
815
|
+
};
|
|
816
|
+
};
|
|
817
|
+
const resolveStartCursor = (state, incoming, seed) => incoming ?? state.cursor ?? {
|
|
818
|
+
watermark: truncateToSecond(state.lastPolledAt ?? seed),
|
|
819
|
+
boundaryIds: state.lastPolledAt ? state.boundaryIds ?? [] : []
|
|
820
|
+
};
|
|
821
|
+
const nextPollingState = (state, seed, result) => {
|
|
822
|
+
if (result.drained) return {
|
|
823
|
+
lastPolledAt: result.cursor.watermark,
|
|
824
|
+
boundaryIds: result.cursor.boundaryIds
|
|
825
|
+
};
|
|
826
|
+
return {
|
|
827
|
+
lastPolledAt: state.lastPolledAt ?? seed,
|
|
828
|
+
...state.lastPolledAt && state.boundaryIds ? { boundaryIds: state.boundaryIds } : {},
|
|
829
|
+
cursor: result.cursor
|
|
830
|
+
};
|
|
831
|
+
};
|
|
832
|
+
//#endregion
|
|
833
|
+
//#region src/util/webhooks.ts
|
|
834
|
+
const escapeXml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
835
|
+
const toWebhookXml = (fields) => {
|
|
836
|
+
return `<webhook>${Object.entries(fields).filter(([, value]) => value !== void 0).map(([key, value]) => `<${key}>${escapeXml(String(value))}</${key}>`).join("")}</webhook>`;
|
|
837
|
+
};
|
|
838
|
+
const parseWebhookId = (data) => {
|
|
839
|
+
if (data && typeof data === "object") {
|
|
840
|
+
const id = data.webhook?.id;
|
|
841
|
+
if (id !== void 0) return Number(id);
|
|
842
|
+
}
|
|
843
|
+
if (typeof data === "string") {
|
|
844
|
+
const match = data.match(/<id>(\d+)<\/id>/);
|
|
845
|
+
if (match) return Number(match[1]);
|
|
846
|
+
}
|
|
847
|
+
};
|
|
848
|
+
const getStoreKey = (flowStableId) => `webhookEvents:${flowStableId}`;
|
|
849
|
+
const buildWebhookName = (flowName, event, suffix) => {
|
|
850
|
+
const fixed = ` - ${event} - ${suffix}`;
|
|
851
|
+
return `${flowName.slice(0, 100 - fixed.length)}${fixed}`;
|
|
852
|
+
};
|
|
853
|
+
const createManagedWebhooks = async (context, { connection, events }) => {
|
|
854
|
+
const client = await createClassicClient(connection, context.debug.enabled);
|
|
855
|
+
const targetUrl = context.webhookUrls[context.flow.name];
|
|
856
|
+
const storeKey = getStoreKey(context.flow.stableId);
|
|
857
|
+
const previous = context.crossFlowState[storeKey];
|
|
858
|
+
for (const id of previous?.webhookIds ?? []) try {
|
|
859
|
+
await client.delete(`/webhooks/id/${id}`);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
context.logger.warn(`Failed to remove previous webhook ${id}: ${_prismatic_io_spectral.util.types.toString(error)}`);
|
|
862
|
+
}
|
|
863
|
+
const webhookAuthValue = (0, node_crypto.randomUUID)();
|
|
864
|
+
const nameSuffix = (0, node_crypto.randomUUID)().slice(0, 8);
|
|
865
|
+
const webhookIds = [];
|
|
866
|
+
try {
|
|
867
|
+
for (const event of events) {
|
|
868
|
+
const body = toWebhookXml({
|
|
869
|
+
name: buildWebhookName(context.flow.name, event, nameSuffix),
|
|
870
|
+
event,
|
|
871
|
+
url: targetUrl,
|
|
872
|
+
content_type: "application/json",
|
|
873
|
+
enabled: true,
|
|
874
|
+
authentication_type: "HEADER",
|
|
875
|
+
header: JSON.stringify({ [WEBHOOK_AUTH_HEADER]: webhookAuthValue })
|
|
876
|
+
});
|
|
877
|
+
const { data } = await client.post("/webhooks/id/0", body, { headers: { "Content-Type": "application/xml" } });
|
|
878
|
+
const id = parseWebhookId(data);
|
|
879
|
+
if (id != null) webhookIds.push(id);
|
|
880
|
+
}
|
|
881
|
+
} catch (error) {
|
|
882
|
+
for (const id of webhookIds) try {
|
|
883
|
+
await client.delete(`/webhooks/id/${id}`);
|
|
884
|
+
} catch {}
|
|
885
|
+
throw error;
|
|
886
|
+
}
|
|
887
|
+
context.crossFlowState[storeKey] = {
|
|
888
|
+
webhookIds,
|
|
889
|
+
webhookAuthValue
|
|
890
|
+
};
|
|
891
|
+
return { crossFlowState: context.crossFlowState };
|
|
892
|
+
};
|
|
893
|
+
const deleteManagedWebhooks = async (context, { connection }) => {
|
|
894
|
+
const client = await createClassicClient(connection, context.debug.enabled);
|
|
895
|
+
const storeKey = getStoreKey(context.flow.stableId);
|
|
896
|
+
const state = context.crossFlowState[storeKey];
|
|
897
|
+
for (const id of state?.webhookIds ?? []) try {
|
|
898
|
+
await client.delete(`/webhooks/id/${id}`);
|
|
899
|
+
} catch (error) {
|
|
900
|
+
context.logger.error(`Failed to delete webhook ${id}: ${_prismatic_io_spectral.util.types.toString(error)}`);
|
|
901
|
+
}
|
|
902
|
+
context.crossFlowState[storeKey] = void 0;
|
|
903
|
+
return { crossFlowState: context.crossFlowState };
|
|
904
|
+
};
|
|
905
|
+
//#endregion
|
|
906
|
+
//#region src/inputs/common.ts
|
|
907
|
+
const connection = (0, _prismatic_io_spectral.input)({
|
|
908
|
+
label: "Connection",
|
|
909
|
+
type: "connection",
|
|
910
|
+
required: true,
|
|
911
|
+
comments: "The Jamf Pro connection to use."
|
|
912
|
+
});
|
|
913
|
+
const resourceId = (0, _prismatic_io_spectral.input)({
|
|
914
|
+
label: "ID",
|
|
915
|
+
type: "string",
|
|
916
|
+
required: true,
|
|
917
|
+
comments: "The unique identifier of the resource.",
|
|
918
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
919
|
+
placeholder: "Enter resource ID",
|
|
920
|
+
example: "1"
|
|
921
|
+
});
|
|
922
|
+
const page = (0, _prismatic_io_spectral.input)({
|
|
923
|
+
label: "Page",
|
|
924
|
+
type: "string",
|
|
925
|
+
required: false,
|
|
926
|
+
default: "0",
|
|
927
|
+
comments: "The zero-indexed page number for paginated results. Page 0 is the first page.",
|
|
928
|
+
clean: toOptionalString,
|
|
929
|
+
placeholder: "Enter page number",
|
|
930
|
+
example: "0"
|
|
931
|
+
});
|
|
932
|
+
const pageSize = (0, _prismatic_io_spectral.input)({
|
|
933
|
+
label: "Page Size",
|
|
934
|
+
type: "string",
|
|
935
|
+
required: false,
|
|
936
|
+
comments: "The maximum number of results to return per page. Maximum 1000.",
|
|
937
|
+
clean: toOptionalString,
|
|
938
|
+
placeholder: "Enter page size",
|
|
939
|
+
example: "100",
|
|
940
|
+
default: "100"
|
|
941
|
+
});
|
|
942
|
+
const filter = (0, _prismatic_io_spectral.input)({
|
|
943
|
+
label: "Filter",
|
|
944
|
+
type: "string",
|
|
945
|
+
required: false,
|
|
946
|
+
comments: "An RSQL filter expression to narrow results. Example: name==\"Apps*\" or id>=5. Leave blank to return all results.",
|
|
947
|
+
clean: toOptionalString,
|
|
948
|
+
placeholder: "Enter filter expression",
|
|
949
|
+
example: "name==\"Acme*\""
|
|
950
|
+
});
|
|
951
|
+
const sort = (0, _prismatic_io_spectral.input)({
|
|
952
|
+
label: "Sort",
|
|
953
|
+
type: "string",
|
|
954
|
+
required: false,
|
|
955
|
+
comments: "The sort criteria in the format property:asc or property:desc. Multiple criteria are comma-separated.",
|
|
956
|
+
clean: toOptionalString,
|
|
957
|
+
placeholder: "Enter sort criteria",
|
|
958
|
+
example: "name:asc,id:desc"
|
|
959
|
+
});
|
|
960
|
+
const fetchAll = (0, _prismatic_io_spectral.input)({
|
|
961
|
+
label: "Fetch All",
|
|
962
|
+
type: "boolean",
|
|
963
|
+
required: false,
|
|
964
|
+
default: "false",
|
|
965
|
+
comments: "If true, fetch every page of results and ignore the Page and Page Size inputs. If false, return a single page.",
|
|
966
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
967
|
+
});
|
|
968
|
+
//#endregion
|
|
969
|
+
//#region src/inputs/categories.ts
|
|
970
|
+
const categoryName = (0, _prismatic_io_spectral.input)({
|
|
971
|
+
label: "Name",
|
|
972
|
+
type: "string",
|
|
973
|
+
required: true,
|
|
974
|
+
comments: "The display name used to identify the category in Jamf Pro.",
|
|
975
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
976
|
+
placeholder: "Enter category name",
|
|
977
|
+
example: "Productivity Apps"
|
|
978
|
+
});
|
|
979
|
+
const priority = (0, _prismatic_io_spectral.input)({
|
|
980
|
+
label: "Priority",
|
|
981
|
+
type: "string",
|
|
982
|
+
required: false,
|
|
983
|
+
default: "9",
|
|
984
|
+
comments: "The sort order weight for the category. Lower numbers appear first.",
|
|
985
|
+
clean: _prismatic_io_spectral.util.types.toNumber,
|
|
986
|
+
placeholder: "Enter priority",
|
|
987
|
+
example: "9"
|
|
988
|
+
});
|
|
989
|
+
const categoryResourceId = {
|
|
990
|
+
...resourceId,
|
|
991
|
+
label: "Category",
|
|
992
|
+
comments: "The unique identifier of the category.",
|
|
993
|
+
dataSource: "selectCategory"
|
|
994
|
+
};
|
|
995
|
+
const createCategoryInputs = {
|
|
996
|
+
connection,
|
|
997
|
+
categoryName,
|
|
998
|
+
priority
|
|
999
|
+
};
|
|
1000
|
+
const deleteCategoryInputs = {
|
|
1001
|
+
connection,
|
|
1002
|
+
resourceId: categoryResourceId
|
|
1003
|
+
};
|
|
1004
|
+
const getCategoryInputs = {
|
|
1005
|
+
connection,
|
|
1006
|
+
resourceId: categoryResourceId
|
|
1007
|
+
};
|
|
1008
|
+
const listCategoriesInputs = {
|
|
1009
|
+
connection,
|
|
1010
|
+
fetchAll,
|
|
1011
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1012
|
+
label: "Pagination",
|
|
1013
|
+
required: false,
|
|
1014
|
+
comments: "Page and page-size controls.",
|
|
1015
|
+
inputs: {
|
|
1016
|
+
page,
|
|
1017
|
+
pageSize
|
|
1018
|
+
}
|
|
1019
|
+
}),
|
|
1020
|
+
sort,
|
|
1021
|
+
filter
|
|
1022
|
+
};
|
|
1023
|
+
const updateCategoryInputs = {
|
|
1024
|
+
connection,
|
|
1025
|
+
resourceId: categoryResourceId,
|
|
1026
|
+
categoryName: {
|
|
1027
|
+
...categoryName,
|
|
1028
|
+
required: false,
|
|
1029
|
+
clean: toOptionalString
|
|
1030
|
+
},
|
|
1031
|
+
priority: {
|
|
1032
|
+
...priority,
|
|
1033
|
+
default: void 0,
|
|
1034
|
+
clean: toOptionalNumber
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
//#endregion
|
|
1038
|
+
//#region src/inputs/computers.ts
|
|
1039
|
+
const section$1 = (0, _prismatic_io_spectral.input)({
|
|
1040
|
+
label: "Section",
|
|
1041
|
+
type: "string",
|
|
1042
|
+
collection: "valuelist",
|
|
1043
|
+
default: ["GENERAL"],
|
|
1044
|
+
model: [
|
|
1045
|
+
{
|
|
1046
|
+
label: "GENERAL",
|
|
1047
|
+
value: "GENERAL"
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
label: "DISK_ENCRYPTION",
|
|
1051
|
+
value: "DISK_ENCRYPTION"
|
|
1052
|
+
},
|
|
1053
|
+
{
|
|
1054
|
+
label: "PURCHASING",
|
|
1055
|
+
value: "PURCHASING"
|
|
1056
|
+
},
|
|
1057
|
+
{
|
|
1058
|
+
label: "APPLICATIONS",
|
|
1059
|
+
value: "APPLICATIONS"
|
|
1060
|
+
},
|
|
1061
|
+
{
|
|
1062
|
+
label: "STORAGE",
|
|
1063
|
+
value: "STORAGE"
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
label: "USER_AND_LOCATION",
|
|
1067
|
+
value: "USER_AND_LOCATION"
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
label: "CONFIGURATION_PROFILES",
|
|
1071
|
+
value: "CONFIGURATION_PROFILES"
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
label: "PRINTERS",
|
|
1075
|
+
value: "PRINTERS"
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
label: "SERVICES",
|
|
1079
|
+
value: "SERVICES"
|
|
1080
|
+
},
|
|
1081
|
+
{
|
|
1082
|
+
label: "HARDWARE",
|
|
1083
|
+
value: "HARDWARE"
|
|
1084
|
+
},
|
|
1085
|
+
{
|
|
1086
|
+
label: "LOCAL_USER_ACCOUNTS",
|
|
1087
|
+
value: "LOCAL_USER_ACCOUNTS"
|
|
1088
|
+
},
|
|
1089
|
+
{
|
|
1090
|
+
label: "CERTIFICATES",
|
|
1091
|
+
value: "CERTIFICATES"
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
label: "ATTACHMENTS",
|
|
1095
|
+
value: "ATTACHMENTS"
|
|
1096
|
+
},
|
|
1097
|
+
{
|
|
1098
|
+
label: "PACKAGE_RECEIPTS",
|
|
1099
|
+
value: "PACKAGE_RECEIPTS"
|
|
1100
|
+
},
|
|
1101
|
+
{
|
|
1102
|
+
label: "SECURITY",
|
|
1103
|
+
value: "SECURITY"
|
|
1104
|
+
},
|
|
1105
|
+
{
|
|
1106
|
+
label: "OPERATING_SYSTEM",
|
|
1107
|
+
value: "OPERATING_SYSTEM"
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
label: "LICENSED_SOFTWARE",
|
|
1111
|
+
value: "LICENSED_SOFTWARE"
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
label: "IBEACONS",
|
|
1115
|
+
value: "IBEACONS"
|
|
1116
|
+
},
|
|
1117
|
+
{
|
|
1118
|
+
label: "SOFTWARE_UPDATES",
|
|
1119
|
+
value: "SOFTWARE_UPDATES"
|
|
1120
|
+
},
|
|
1121
|
+
{
|
|
1122
|
+
label: "EXTENSION_ATTRIBUTES",
|
|
1123
|
+
value: "EXTENSION_ATTRIBUTES"
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
label: "CONTENT_CACHING",
|
|
1127
|
+
value: "CONTENT_CACHING"
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
label: "GROUP_MEMBERSHIPS",
|
|
1131
|
+
value: "GROUP_MEMBERSHIPS"
|
|
1132
|
+
}
|
|
1133
|
+
],
|
|
1134
|
+
comments: "Section of computer details to include in the response. If not specified, General section data is returned.",
|
|
1135
|
+
clean: asStringArray,
|
|
1136
|
+
placeholder: "Enter section",
|
|
1137
|
+
example: "GENERAL"
|
|
1138
|
+
});
|
|
1139
|
+
const computerUpdateBody = (0, _prismatic_io_spectral.input)({
|
|
1140
|
+
label: "Update Data",
|
|
1141
|
+
language: "json",
|
|
1142
|
+
type: "code",
|
|
1143
|
+
required: true,
|
|
1144
|
+
comments: "JSON object with the computer inventory fields to update. Only the provided fields will be modified (PATCH semantics).",
|
|
1145
|
+
clean: _prismatic_io_spectral.util.types.toObject,
|
|
1146
|
+
placeholder: "Enter update data as JSON",
|
|
1147
|
+
example: JSON.stringify({
|
|
1148
|
+
udid: "45436edf-864e-4364-982a-330b01d39e65",
|
|
1149
|
+
general: {
|
|
1150
|
+
name: "Boalime",
|
|
1151
|
+
lastIpAddress: "247.185.82.186",
|
|
1152
|
+
barcode1: "5 12345 678900",
|
|
1153
|
+
barcode2: "5 12345 678900",
|
|
1154
|
+
assetTag: "304822",
|
|
1155
|
+
managed: true,
|
|
1156
|
+
siteId: "1"
|
|
1157
|
+
},
|
|
1158
|
+
userAndLocation: {
|
|
1159
|
+
username: "Madison Anderson",
|
|
1160
|
+
realname: "13-inch MacBook",
|
|
1161
|
+
email: "email@com.pl",
|
|
1162
|
+
position: "IT Team Lead",
|
|
1163
|
+
phone: "123-456-789",
|
|
1164
|
+
departmentId: "1",
|
|
1165
|
+
buildingId: "1",
|
|
1166
|
+
room: "5",
|
|
1167
|
+
extensionAttributes: [{
|
|
1168
|
+
definitionId: "23",
|
|
1169
|
+
values: ["foo", "bar"]
|
|
1170
|
+
}]
|
|
1171
|
+
},
|
|
1172
|
+
hardware: {
|
|
1173
|
+
networkAdapterType: "Foo",
|
|
1174
|
+
macAddress: "6A:2C:4B:B7:65:B5",
|
|
1175
|
+
altNetworkAdapterType: "Bar",
|
|
1176
|
+
altMacAddress: "82:45:58:44:dc:01",
|
|
1177
|
+
extensionAttributes: [{
|
|
1178
|
+
definitionId: "23",
|
|
1179
|
+
values: ["foo", "bar"]
|
|
1180
|
+
}]
|
|
1181
|
+
}
|
|
1182
|
+
}, null, 2)
|
|
1183
|
+
});
|
|
1184
|
+
const listComputersInputs = {
|
|
1185
|
+
connection,
|
|
1186
|
+
fetchAll,
|
|
1187
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1188
|
+
label: "Pagination",
|
|
1189
|
+
required: false,
|
|
1190
|
+
comments: "Page and page-size controls.",
|
|
1191
|
+
inputs: {
|
|
1192
|
+
page,
|
|
1193
|
+
pageSize
|
|
1194
|
+
}
|
|
1195
|
+
}),
|
|
1196
|
+
sort,
|
|
1197
|
+
filter,
|
|
1198
|
+
section: section$1
|
|
1199
|
+
};
|
|
1200
|
+
const computerResourceId = {
|
|
1201
|
+
...resourceId,
|
|
1202
|
+
label: "Computer",
|
|
1203
|
+
comments: "The unique identifier of the computer.",
|
|
1204
|
+
dataSource: "selectComputer"
|
|
1205
|
+
};
|
|
1206
|
+
const getComputerInputs = {
|
|
1207
|
+
connection,
|
|
1208
|
+
resourceId: computerResourceId,
|
|
1209
|
+
section: section$1
|
|
1210
|
+
};
|
|
1211
|
+
const updateComputerInputs = {
|
|
1212
|
+
connection,
|
|
1213
|
+
resourceId: computerResourceId,
|
|
1214
|
+
computerUpdateBody
|
|
1215
|
+
};
|
|
1216
|
+
//#endregion
|
|
1217
|
+
//#region src/inputs/dataSources.ts
|
|
1218
|
+
const selectCategoryInputs = { connection };
|
|
1219
|
+
const selectComputerInputs = { connection };
|
|
1220
|
+
const selectDepartmentInputs = { connection };
|
|
1221
|
+
const selectMobileDeviceInputs = { connection };
|
|
1222
|
+
const selectPackageInputs = { connection };
|
|
1223
|
+
const selectScriptInputs = { connection };
|
|
1224
|
+
const selectWebhookInputs = { connection };
|
|
1225
|
+
//#endregion
|
|
1226
|
+
//#region src/inputs/departments.ts
|
|
1227
|
+
const departmentName = (0, _prismatic_io_spectral.input)({
|
|
1228
|
+
label: "Name",
|
|
1229
|
+
type: "string",
|
|
1230
|
+
required: true,
|
|
1231
|
+
comments: "The display name used to identify the department in Jamf Pro.",
|
|
1232
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1233
|
+
placeholder: "Enter department name",
|
|
1234
|
+
example: "Information Technology"
|
|
1235
|
+
});
|
|
1236
|
+
const departmentResourceId = {
|
|
1237
|
+
...resourceId,
|
|
1238
|
+
label: "Department",
|
|
1239
|
+
comments: "The unique identifier of the department.",
|
|
1240
|
+
dataSource: "selectDepartment"
|
|
1241
|
+
};
|
|
1242
|
+
const createDepartmentInputs = {
|
|
1243
|
+
connection,
|
|
1244
|
+
departmentName
|
|
1245
|
+
};
|
|
1246
|
+
const deleteDepartmentInputs = {
|
|
1247
|
+
connection,
|
|
1248
|
+
resourceId: departmentResourceId
|
|
1249
|
+
};
|
|
1250
|
+
const getDepartmentInputs = {
|
|
1251
|
+
connection,
|
|
1252
|
+
resourceId: departmentResourceId
|
|
1253
|
+
};
|
|
1254
|
+
const listDepartmentsInputs = {
|
|
1255
|
+
connection,
|
|
1256
|
+
fetchAll,
|
|
1257
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1258
|
+
label: "Pagination",
|
|
1259
|
+
required: false,
|
|
1260
|
+
comments: "Page and page-size controls.",
|
|
1261
|
+
inputs: {
|
|
1262
|
+
page,
|
|
1263
|
+
pageSize
|
|
1264
|
+
}
|
|
1265
|
+
}),
|
|
1266
|
+
sort,
|
|
1267
|
+
filter
|
|
1268
|
+
};
|
|
1269
|
+
const updateDepartmentInputs = {
|
|
1270
|
+
connection,
|
|
1271
|
+
resourceId: departmentResourceId,
|
|
1272
|
+
departmentName
|
|
1273
|
+
};
|
|
1274
|
+
//#endregion
|
|
1275
|
+
//#region src/inputs/misc.ts
|
|
1276
|
+
const { debugRequest: _, ...httpInputs } = _prismatic_io_spectral_http.inputs;
|
|
1277
|
+
const rawRequestInputs = {
|
|
1278
|
+
connection,
|
|
1279
|
+
apiType: (0, _prismatic_io_spectral.input)({
|
|
1280
|
+
label: "API",
|
|
1281
|
+
type: "string",
|
|
1282
|
+
required: false,
|
|
1283
|
+
default: "api",
|
|
1284
|
+
model: [{
|
|
1285
|
+
label: "Pro API",
|
|
1286
|
+
value: "api"
|
|
1287
|
+
}, {
|
|
1288
|
+
label: "Classic API",
|
|
1289
|
+
value: "JSSResource"
|
|
1290
|
+
}],
|
|
1291
|
+
comments: "Which Jamf Pro API to target. The Pro API uses the /api base path; the Classic API uses /JSSResource.",
|
|
1292
|
+
clean: _prismatic_io_spectral.util.types.toString
|
|
1293
|
+
}),
|
|
1294
|
+
...httpInputs,
|
|
1295
|
+
url: {
|
|
1296
|
+
...httpInputs.url,
|
|
1297
|
+
comments: "The API path only (e.g., /v1/computers-inventory for the Pro API, or /computers/id/1 for the Classic API). The base URL and selected API prefix are added automatically.",
|
|
1298
|
+
example: "/v1/computers-inventory"
|
|
1299
|
+
}
|
|
1300
|
+
};
|
|
1301
|
+
//#endregion
|
|
1302
|
+
//#region src/inputs/mobileDevices.ts
|
|
1303
|
+
const section = (0, _prismatic_io_spectral.input)({
|
|
1304
|
+
label: "Section",
|
|
1305
|
+
type: "string",
|
|
1306
|
+
collection: "valuelist",
|
|
1307
|
+
default: ["GENERAL"],
|
|
1308
|
+
model: [
|
|
1309
|
+
{
|
|
1310
|
+
label: "GENERAL",
|
|
1311
|
+
value: "GENERAL"
|
|
1312
|
+
},
|
|
1313
|
+
{
|
|
1314
|
+
label: "HARDWARE",
|
|
1315
|
+
value: "HARDWARE"
|
|
1316
|
+
},
|
|
1317
|
+
{
|
|
1318
|
+
label: "USER_AND_LOCATION",
|
|
1319
|
+
value: "USER_AND_LOCATION"
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
label: "PURCHASING",
|
|
1323
|
+
value: "PURCHASING"
|
|
1324
|
+
},
|
|
1325
|
+
{
|
|
1326
|
+
label: "SECURITY",
|
|
1327
|
+
value: "SECURITY"
|
|
1328
|
+
},
|
|
1329
|
+
{
|
|
1330
|
+
label: "APPLICATIONS",
|
|
1331
|
+
value: "APPLICATIONS"
|
|
1332
|
+
},
|
|
1333
|
+
{
|
|
1334
|
+
label: "EBOOKS",
|
|
1335
|
+
value: "EBOOKS"
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
label: "NETWORK",
|
|
1339
|
+
value: "NETWORK"
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
label: "SERVICE_SUBSCRIPTIONS",
|
|
1343
|
+
value: "SERVICE_SUBSCRIPTIONS"
|
|
1344
|
+
},
|
|
1345
|
+
{
|
|
1346
|
+
label: "CERTIFICATES",
|
|
1347
|
+
value: "CERTIFICATES"
|
|
1348
|
+
},
|
|
1349
|
+
{
|
|
1350
|
+
label: "PROFILES",
|
|
1351
|
+
value: "PROFILES"
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
label: "USER_PROFILES",
|
|
1355
|
+
value: "USER_PROFILES"
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
label: "PROVISIONING_PROFILES",
|
|
1359
|
+
value: "PROVISIONING_PROFILES"
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
label: "SHARED_USERS",
|
|
1363
|
+
value: "SHARED_USERS"
|
|
1364
|
+
},
|
|
1365
|
+
{
|
|
1366
|
+
label: "GROUPS",
|
|
1367
|
+
value: "GROUPS"
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
label: "EXTENSION_ATTRIBUTES",
|
|
1371
|
+
value: "EXTENSION_ATTRIBUTES"
|
|
1372
|
+
}
|
|
1373
|
+
],
|
|
1374
|
+
comments: "Section of mobile device details to include in the response. If not specified, General section data is returned.",
|
|
1375
|
+
clean: asStringArray,
|
|
1376
|
+
placeholder: "Enter section",
|
|
1377
|
+
example: "GENERAL"
|
|
1378
|
+
});
|
|
1379
|
+
const mobileDeviceResourceId = {
|
|
1380
|
+
...resourceId,
|
|
1381
|
+
label: "Mobile Device",
|
|
1382
|
+
comments: "The unique identifier of the mobile device.",
|
|
1383
|
+
dataSource: "selectMobileDevice"
|
|
1384
|
+
};
|
|
1385
|
+
const listMobileDevicesInputs = {
|
|
1386
|
+
connection,
|
|
1387
|
+
fetchAll,
|
|
1388
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1389
|
+
label: "Pagination",
|
|
1390
|
+
required: false,
|
|
1391
|
+
comments: "Page and page-size controls.",
|
|
1392
|
+
inputs: {
|
|
1393
|
+
page,
|
|
1394
|
+
pageSize
|
|
1395
|
+
}
|
|
1396
|
+
}),
|
|
1397
|
+
sort,
|
|
1398
|
+
filter,
|
|
1399
|
+
section
|
|
1400
|
+
};
|
|
1401
|
+
const getMobileDeviceInputs = {
|
|
1402
|
+
connection,
|
|
1403
|
+
resourceId: mobileDeviceResourceId
|
|
1404
|
+
};
|
|
1405
|
+
//#endregion
|
|
1406
|
+
//#region src/inputs/packages.ts
|
|
1407
|
+
const optionalBoolean$1 = (label, comments) => (0, _prismatic_io_spectral.input)({
|
|
1408
|
+
label,
|
|
1409
|
+
type: "string",
|
|
1410
|
+
required: false,
|
|
1411
|
+
model: [{
|
|
1412
|
+
label: "True",
|
|
1413
|
+
value: "true"
|
|
1414
|
+
}, {
|
|
1415
|
+
label: "False",
|
|
1416
|
+
value: "false"
|
|
1417
|
+
}],
|
|
1418
|
+
comments,
|
|
1419
|
+
clean: toOptionalBool
|
|
1420
|
+
});
|
|
1421
|
+
const packageName = (0, _prismatic_io_spectral.input)({
|
|
1422
|
+
label: "Package Name",
|
|
1423
|
+
type: "string",
|
|
1424
|
+
required: true,
|
|
1425
|
+
comments: "The display name of the package as shown in Jamf Pro.",
|
|
1426
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1427
|
+
placeholder: "Enter package name",
|
|
1428
|
+
example: "Google Chrome 120.0.pkg"
|
|
1429
|
+
});
|
|
1430
|
+
const packageFileName = (0, _prismatic_io_spectral.input)({
|
|
1431
|
+
label: "File Name",
|
|
1432
|
+
type: "string",
|
|
1433
|
+
required: true,
|
|
1434
|
+
comments: "The filename of the package file on the Jamf distribution point (e.g., GoogleChrome.pkg).",
|
|
1435
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1436
|
+
placeholder: "Enter file name",
|
|
1437
|
+
example: "GoogleChrome-120.0.6099.199.pkg"
|
|
1438
|
+
});
|
|
1439
|
+
const packageCategoryId = (0, _prismatic_io_spectral.input)({
|
|
1440
|
+
label: "Category ID",
|
|
1441
|
+
type: "string",
|
|
1442
|
+
required: false,
|
|
1443
|
+
dataSource: "selectCategory",
|
|
1444
|
+
comments: "The unique identifier of the category to assign to this package.",
|
|
1445
|
+
clean: toOptionalString,
|
|
1446
|
+
placeholder: "Enter category ID",
|
|
1447
|
+
example: "3"
|
|
1448
|
+
});
|
|
1449
|
+
const packageInfo = (0, _prismatic_io_spectral.input)({
|
|
1450
|
+
label: "Info",
|
|
1451
|
+
type: "string",
|
|
1452
|
+
required: false,
|
|
1453
|
+
comments: "A description of the package displayed to administrators in Jamf Pro.",
|
|
1454
|
+
clean: toOptionalString,
|
|
1455
|
+
placeholder: "Enter package info",
|
|
1456
|
+
example: "Google Chrome browser installer."
|
|
1457
|
+
});
|
|
1458
|
+
const packageNotes = (0, _prismatic_io_spectral.input)({
|
|
1459
|
+
label: "Notes",
|
|
1460
|
+
type: "string",
|
|
1461
|
+
required: false,
|
|
1462
|
+
comments: "Internal notes about the package visible only to administrators.",
|
|
1463
|
+
clean: toOptionalString,
|
|
1464
|
+
placeholder: "Enter notes",
|
|
1465
|
+
example: "Downloaded from https://dl.google.com/chrome/mac/stable/"
|
|
1466
|
+
});
|
|
1467
|
+
const packagePriority = (0, _prismatic_io_spectral.input)({
|
|
1468
|
+
label: "Priority",
|
|
1469
|
+
type: "string",
|
|
1470
|
+
required: false,
|
|
1471
|
+
comments: "Installation priority from 1 (highest) to 20 (lowest). Defaults to 10.",
|
|
1472
|
+
clean: toOptionalNumber,
|
|
1473
|
+
placeholder: "Enter priority (1–20)",
|
|
1474
|
+
example: "10"
|
|
1475
|
+
});
|
|
1476
|
+
const createPackageInputs = {
|
|
1477
|
+
connection,
|
|
1478
|
+
packageName,
|
|
1479
|
+
packageFileName,
|
|
1480
|
+
packageCategoryId,
|
|
1481
|
+
additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1482
|
+
label: "Additional Fields",
|
|
1483
|
+
required: false,
|
|
1484
|
+
comments: "Additional optional fields: includes Priority, Info, Notes, Reboot Required, OS Install, Fill User Template, Suppress Updates, Suppress EULA, Suppress From Dock, and Suppress Registration.",
|
|
1485
|
+
inputs: {
|
|
1486
|
+
packagePriority,
|
|
1487
|
+
packageInfo,
|
|
1488
|
+
packageNotes,
|
|
1489
|
+
packageRebootRequired: (0, _prismatic_io_spectral.input)({
|
|
1490
|
+
label: "Reboot Required",
|
|
1491
|
+
type: "boolean",
|
|
1492
|
+
required: false,
|
|
1493
|
+
comments: "Whether the device must reboot after installing this package.",
|
|
1494
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1495
|
+
}),
|
|
1496
|
+
packageOsInstall: (0, _prismatic_io_spectral.input)({
|
|
1497
|
+
label: "OS Install",
|
|
1498
|
+
type: "boolean",
|
|
1499
|
+
required: false,
|
|
1500
|
+
comments: "Whether this package is an OS installer.",
|
|
1501
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1502
|
+
}),
|
|
1503
|
+
packageFillUserTemplate: (0, _prismatic_io_spectral.input)({
|
|
1504
|
+
label: "Fill User Template",
|
|
1505
|
+
type: "boolean",
|
|
1506
|
+
required: false,
|
|
1507
|
+
comments: "Whether to fill the user template with the package contents.",
|
|
1508
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1509
|
+
}),
|
|
1510
|
+
packageSuppressUpdates: (0, _prismatic_io_spectral.input)({
|
|
1511
|
+
label: "Suppress Updates",
|
|
1512
|
+
type: "boolean",
|
|
1513
|
+
required: false,
|
|
1514
|
+
comments: "Whether to suppress software updates during installation.",
|
|
1515
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1516
|
+
}),
|
|
1517
|
+
packageSuppressEula: (0, _prismatic_io_spectral.input)({
|
|
1518
|
+
label: "Suppress EULA",
|
|
1519
|
+
type: "boolean",
|
|
1520
|
+
required: false,
|
|
1521
|
+
comments: "Whether to suppress the End User License Agreement during installation.",
|
|
1522
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1523
|
+
}),
|
|
1524
|
+
packageSuppressFromDock: (0, _prismatic_io_spectral.input)({
|
|
1525
|
+
label: "Suppress From Dock",
|
|
1526
|
+
type: "boolean",
|
|
1527
|
+
required: false,
|
|
1528
|
+
comments: "Whether to suppress the package icon from the Dock during installation.",
|
|
1529
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1530
|
+
}),
|
|
1531
|
+
packageSuppressRegistration: (0, _prismatic_io_spectral.input)({
|
|
1532
|
+
label: "Suppress Registration",
|
|
1533
|
+
type: "boolean",
|
|
1534
|
+
required: false,
|
|
1535
|
+
comments: "Whether to suppress the registration window during installation.",
|
|
1536
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1537
|
+
})
|
|
1538
|
+
}
|
|
1539
|
+
})
|
|
1540
|
+
};
|
|
1541
|
+
const packageResourceId = {
|
|
1542
|
+
...resourceId,
|
|
1543
|
+
label: "Package",
|
|
1544
|
+
comments: "The unique identifier of the package.",
|
|
1545
|
+
dataSource: "selectPackage"
|
|
1546
|
+
};
|
|
1547
|
+
const deletePackageInputs = {
|
|
1548
|
+
connection,
|
|
1549
|
+
resourceId: packageResourceId
|
|
1550
|
+
};
|
|
1551
|
+
const getPackageInputs = {
|
|
1552
|
+
connection,
|
|
1553
|
+
resourceId: packageResourceId
|
|
1554
|
+
};
|
|
1555
|
+
const listPackagesInputs = {
|
|
1556
|
+
connection,
|
|
1557
|
+
fetchAll,
|
|
1558
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1559
|
+
label: "Pagination",
|
|
1560
|
+
required: false,
|
|
1561
|
+
comments: "Page and page-size controls.",
|
|
1562
|
+
inputs: {
|
|
1563
|
+
page,
|
|
1564
|
+
pageSize
|
|
1565
|
+
}
|
|
1566
|
+
}),
|
|
1567
|
+
sort,
|
|
1568
|
+
filter
|
|
1569
|
+
};
|
|
1570
|
+
const updatePackageInputs = {
|
|
1571
|
+
connection,
|
|
1572
|
+
resourceId: packageResourceId,
|
|
1573
|
+
packageCategoryId,
|
|
1574
|
+
additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1575
|
+
label: "Additional Fields",
|
|
1576
|
+
required: false,
|
|
1577
|
+
comments: "Additional optional fields: includes Package Name, File Name, Priority, Info, Notes, Reboot Required, OS Install, Fill User Template, Suppress Updates, Suppress EULA, Suppress From Dock, and Suppress Registration.",
|
|
1578
|
+
inputs: {
|
|
1579
|
+
packageName: {
|
|
1580
|
+
...packageName,
|
|
1581
|
+
required: false,
|
|
1582
|
+
clean: toOptionalString
|
|
1583
|
+
},
|
|
1584
|
+
packageFileName: {
|
|
1585
|
+
...packageFileName,
|
|
1586
|
+
required: false,
|
|
1587
|
+
clean: toOptionalString
|
|
1588
|
+
},
|
|
1589
|
+
packagePriority,
|
|
1590
|
+
packageInfo,
|
|
1591
|
+
packageNotes,
|
|
1592
|
+
packageRebootRequired: optionalBoolean$1("Reboot Required", "Whether the device must reboot after installing this package."),
|
|
1593
|
+
packageOsInstall: optionalBoolean$1("OS Install", "Whether this package is an OS installer."),
|
|
1594
|
+
packageFillUserTemplate: optionalBoolean$1("Fill User Template", "Whether to fill the user template with the package contents."),
|
|
1595
|
+
packageSuppressUpdates: optionalBoolean$1("Suppress Updates", "Whether to suppress software updates during installation."),
|
|
1596
|
+
packageSuppressEula: optionalBoolean$1("Suppress EULA", "Whether to suppress the End User License Agreement during installation."),
|
|
1597
|
+
packageSuppressFromDock: optionalBoolean$1("Suppress From Dock", "Whether to suppress the package icon from the Dock during installation."),
|
|
1598
|
+
packageSuppressRegistration: optionalBoolean$1("Suppress Registration", "Whether to suppress the registration window during installation.")
|
|
1599
|
+
}
|
|
1600
|
+
})
|
|
1601
|
+
};
|
|
1602
|
+
//#endregion
|
|
1603
|
+
//#region src/inputs/scripts.ts
|
|
1604
|
+
const scriptName = (0, _prismatic_io_spectral.input)({
|
|
1605
|
+
label: "Name",
|
|
1606
|
+
type: "string",
|
|
1607
|
+
required: true,
|
|
1608
|
+
comments: "The display name used to identify the script in Jamf Pro.",
|
|
1609
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1610
|
+
placeholder: "Enter script name",
|
|
1611
|
+
example: "Install Chrome"
|
|
1612
|
+
});
|
|
1613
|
+
const scriptContents = (0, _prismatic_io_spectral.input)({
|
|
1614
|
+
label: "Script Contents",
|
|
1615
|
+
type: "text",
|
|
1616
|
+
required: false,
|
|
1617
|
+
comments: "The shell script body. Include the shebang line (e.g., #!/bin/bash).",
|
|
1618
|
+
clean: toOptionalString,
|
|
1619
|
+
placeholder: "Enter script contents",
|
|
1620
|
+
example: "#!/bin/bash\n/usr/local/bin/install-app.sh"
|
|
1621
|
+
});
|
|
1622
|
+
const scriptCategoryId = (0, _prismatic_io_spectral.input)({
|
|
1623
|
+
label: "Category ID",
|
|
1624
|
+
type: "string",
|
|
1625
|
+
required: false,
|
|
1626
|
+
dataSource: "selectCategory",
|
|
1627
|
+
comments: "The unique identifier of the category to assign to this script.",
|
|
1628
|
+
clean: toOptionalString,
|
|
1629
|
+
placeholder: "Enter category ID",
|
|
1630
|
+
example: "3"
|
|
1631
|
+
});
|
|
1632
|
+
const scriptPriority = (0, _prismatic_io_spectral.input)({
|
|
1633
|
+
label: "Priority",
|
|
1634
|
+
type: "string",
|
|
1635
|
+
required: false,
|
|
1636
|
+
default: "AFTER",
|
|
1637
|
+
model: [
|
|
1638
|
+
{
|
|
1639
|
+
label: "BEFORE",
|
|
1640
|
+
value: "BEFORE"
|
|
1641
|
+
},
|
|
1642
|
+
{
|
|
1643
|
+
label: "AFTER",
|
|
1644
|
+
value: "AFTER"
|
|
1645
|
+
},
|
|
1646
|
+
{
|
|
1647
|
+
label: "AT_REBOOT",
|
|
1648
|
+
value: "AT_REBOOT"
|
|
1649
|
+
}
|
|
1650
|
+
],
|
|
1651
|
+
comments: "When the script runs relative to the policy.",
|
|
1652
|
+
clean: toOptionalString,
|
|
1653
|
+
placeholder: "Enter priority",
|
|
1654
|
+
example: "AFTER"
|
|
1655
|
+
});
|
|
1656
|
+
const scriptInfo = (0, _prismatic_io_spectral.input)({
|
|
1657
|
+
label: "Info",
|
|
1658
|
+
type: "string",
|
|
1659
|
+
required: false,
|
|
1660
|
+
comments: "A description of the script displayed to administrators in Jamf Pro.",
|
|
1661
|
+
clean: toOptionalString,
|
|
1662
|
+
placeholder: "Enter script info",
|
|
1663
|
+
example: "Installs Google Chrome from the vendor CDN."
|
|
1664
|
+
});
|
|
1665
|
+
const scriptNotes = (0, _prismatic_io_spectral.input)({
|
|
1666
|
+
label: "Notes",
|
|
1667
|
+
type: "string",
|
|
1668
|
+
required: false,
|
|
1669
|
+
comments: "Internal notes about the script visible only to administrators.",
|
|
1670
|
+
clean: toOptionalString,
|
|
1671
|
+
placeholder: "Enter notes",
|
|
1672
|
+
example: "Updated 2026-01-15 to support macOS 15."
|
|
1673
|
+
});
|
|
1674
|
+
const createScriptInputs = {
|
|
1675
|
+
connection,
|
|
1676
|
+
scriptName,
|
|
1677
|
+
scriptCategoryId,
|
|
1678
|
+
additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1679
|
+
label: "Additional Fields",
|
|
1680
|
+
required: false,
|
|
1681
|
+
comments: "Additional optional fields: includes Script Contents, Priority, Info, and Notes.",
|
|
1682
|
+
inputs: {
|
|
1683
|
+
scriptContents,
|
|
1684
|
+
scriptPriority,
|
|
1685
|
+
scriptInfo,
|
|
1686
|
+
scriptNotes
|
|
1687
|
+
}
|
|
1688
|
+
})
|
|
1689
|
+
};
|
|
1690
|
+
const scriptResourceId = {
|
|
1691
|
+
...resourceId,
|
|
1692
|
+
label: "Script",
|
|
1693
|
+
comments: "The unique identifier of the script.",
|
|
1694
|
+
dataSource: "selectScript"
|
|
1695
|
+
};
|
|
1696
|
+
const deleteScriptInputs = {
|
|
1697
|
+
connection,
|
|
1698
|
+
resourceId: scriptResourceId
|
|
1699
|
+
};
|
|
1700
|
+
const getScriptInputs = {
|
|
1701
|
+
connection,
|
|
1702
|
+
resourceId: scriptResourceId
|
|
1703
|
+
};
|
|
1704
|
+
const listScriptsInputs = {
|
|
1705
|
+
connection,
|
|
1706
|
+
fetchAll,
|
|
1707
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1708
|
+
label: "Pagination",
|
|
1709
|
+
required: false,
|
|
1710
|
+
comments: "Page and page-size controls.",
|
|
1711
|
+
inputs: {
|
|
1712
|
+
page,
|
|
1713
|
+
pageSize
|
|
1714
|
+
}
|
|
1715
|
+
}),
|
|
1716
|
+
sort,
|
|
1717
|
+
filter
|
|
1718
|
+
};
|
|
1719
|
+
const updateScriptInputs = {
|
|
1720
|
+
connection,
|
|
1721
|
+
resourceId: scriptResourceId,
|
|
1722
|
+
scriptCategoryId,
|
|
1723
|
+
additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1724
|
+
label: "Additional Fields",
|
|
1725
|
+
required: false,
|
|
1726
|
+
comments: "Additional optional fields: includes Name, Script Contents, Priority, Info, and Notes.",
|
|
1727
|
+
inputs: {
|
|
1728
|
+
scriptName: {
|
|
1729
|
+
...scriptName,
|
|
1730
|
+
required: false,
|
|
1731
|
+
clean: toOptionalString
|
|
1732
|
+
},
|
|
1733
|
+
scriptContents,
|
|
1734
|
+
scriptPriority: {
|
|
1735
|
+
...scriptPriority,
|
|
1736
|
+
default: void 0
|
|
1737
|
+
},
|
|
1738
|
+
scriptInfo,
|
|
1739
|
+
scriptNotes
|
|
1740
|
+
}
|
|
1741
|
+
})
|
|
1742
|
+
};
|
|
1743
|
+
const webhookInputs = {
|
|
1744
|
+
authHeaderName: (0, _prismatic_io_spectral.input)({
|
|
1745
|
+
label: "Auth Header Name",
|
|
1746
|
+
type: "string",
|
|
1747
|
+
required: false,
|
|
1748
|
+
comments: "Name of the header Jamf Pro sends for header authentication (must match the webhook's configured header). Leave blank to accept all incoming requests.",
|
|
1749
|
+
clean: toOptionalString,
|
|
1750
|
+
placeholder: "X-Jamf-Signature",
|
|
1751
|
+
example: "X-Jamf-Signature"
|
|
1752
|
+
}),
|
|
1753
|
+
authHeaderValue: (0, _prismatic_io_spectral.input)({
|
|
1754
|
+
label: "Auth Header Value",
|
|
1755
|
+
type: "string",
|
|
1756
|
+
required: false,
|
|
1757
|
+
comments: "Expected value of the authentication header. Incoming requests whose header does not match are rejected. Required only if an Auth Header Name is set.",
|
|
1758
|
+
clean: toOptionalString,
|
|
1759
|
+
placeholder: "Enter the expected header value"
|
|
1760
|
+
})
|
|
1761
|
+
};
|
|
1762
|
+
const events = (0, _prismatic_io_spectral.input)({
|
|
1763
|
+
label: "Events",
|
|
1764
|
+
type: "string",
|
|
1765
|
+
collection: "valuelist",
|
|
1766
|
+
required: true,
|
|
1767
|
+
model: webhookEventOptions,
|
|
1768
|
+
default: ["ComputerAdded"],
|
|
1769
|
+
comments: "The Jamf Pro events to subscribe to. One webhook is created per selected event.",
|
|
1770
|
+
clean: asStringArray
|
|
1771
|
+
});
|
|
1772
|
+
const lookBackDate = (0, _prismatic_io_spectral.input)({
|
|
1773
|
+
label: "Look-back Date",
|
|
1774
|
+
placeholder: "Enter look-back date (YYYY-MM-DD)",
|
|
1775
|
+
type: "string",
|
|
1776
|
+
required: false,
|
|
1777
|
+
comments: "The date the initial sync starts from, in YYYY-MM-DD format. Cannot be a future date. Leave empty to start from the first recurrence with no backfill. When set, the initial sync seeds each computer enrolled on or after this date once.",
|
|
1778
|
+
example: "2026-01-01",
|
|
1779
|
+
clean: lookBackDateClean
|
|
1780
|
+
});
|
|
1781
|
+
const webhookEventsInputs = {
|
|
1782
|
+
connection,
|
|
1783
|
+
events
|
|
1784
|
+
};
|
|
1785
|
+
const pollComputersInputs = {
|
|
1786
|
+
connection,
|
|
1787
|
+
lookBackDate
|
|
1788
|
+
};
|
|
1789
|
+
const pollMobileDevicesInputs = { connection };
|
|
1790
|
+
const listUsersInputs = {
|
|
1791
|
+
connection,
|
|
1792
|
+
fetchAll,
|
|
1793
|
+
pagination: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1794
|
+
label: "Pagination",
|
|
1795
|
+
required: false,
|
|
1796
|
+
comments: "Page and page-size controls.",
|
|
1797
|
+
inputs: {
|
|
1798
|
+
page,
|
|
1799
|
+
pageSize
|
|
1800
|
+
}
|
|
1801
|
+
}),
|
|
1802
|
+
sort,
|
|
1803
|
+
filter
|
|
1804
|
+
};
|
|
1805
|
+
//#endregion
|
|
1806
|
+
//#region src/inputs/webhooks.ts
|
|
1807
|
+
const optionalBoolean = (label, comments) => (0, _prismatic_io_spectral.input)({
|
|
1808
|
+
label,
|
|
1809
|
+
type: "string",
|
|
1810
|
+
required: false,
|
|
1811
|
+
model: [{
|
|
1812
|
+
label: "True",
|
|
1813
|
+
value: "true"
|
|
1814
|
+
}, {
|
|
1815
|
+
label: "False",
|
|
1816
|
+
value: "false"
|
|
1817
|
+
}],
|
|
1818
|
+
comments,
|
|
1819
|
+
clean: toOptionalBool
|
|
1820
|
+
});
|
|
1821
|
+
const webhookName = (0, _prismatic_io_spectral.input)({
|
|
1822
|
+
label: "Name",
|
|
1823
|
+
type: "string",
|
|
1824
|
+
required: true,
|
|
1825
|
+
comments: "The display name used to identify the webhook in Jamf Pro.",
|
|
1826
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1827
|
+
placeholder: "Enter webhook name",
|
|
1828
|
+
example: "New Computer Notifier"
|
|
1829
|
+
});
|
|
1830
|
+
const webhookEvent = (0, _prismatic_io_spectral.input)({
|
|
1831
|
+
label: "Event",
|
|
1832
|
+
type: "string",
|
|
1833
|
+
required: true,
|
|
1834
|
+
model: webhookEventOptions,
|
|
1835
|
+
comments: "The Jamf Pro event that triggers this webhook.",
|
|
1836
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1837
|
+
placeholder: "Select an event",
|
|
1838
|
+
example: "ComputerAdded"
|
|
1839
|
+
});
|
|
1840
|
+
const webhookUrl = (0, _prismatic_io_spectral.input)({
|
|
1841
|
+
label: "URL",
|
|
1842
|
+
type: "string",
|
|
1843
|
+
required: true,
|
|
1844
|
+
comments: "The destination URL that Jamf Pro sends webhook events to.",
|
|
1845
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1846
|
+
placeholder: "https://example.com/webhook",
|
|
1847
|
+
example: "https://example.com/webhook"
|
|
1848
|
+
});
|
|
1849
|
+
const webhookContentType = (0, _prismatic_io_spectral.input)({
|
|
1850
|
+
label: "Content Type",
|
|
1851
|
+
type: "string",
|
|
1852
|
+
required: false,
|
|
1853
|
+
default: "application/json",
|
|
1854
|
+
model: [{
|
|
1855
|
+
label: "JSON",
|
|
1856
|
+
value: "application/json"
|
|
1857
|
+
}, {
|
|
1858
|
+
label: "XML",
|
|
1859
|
+
value: "text/xml"
|
|
1860
|
+
}],
|
|
1861
|
+
comments: "The payload format Jamf Pro delivers events in.",
|
|
1862
|
+
clean: _prismatic_io_spectral.util.types.toString,
|
|
1863
|
+
example: "application/json"
|
|
1864
|
+
});
|
|
1865
|
+
const webhookEnabled = (0, _prismatic_io_spectral.input)({
|
|
1866
|
+
label: "Enabled",
|
|
1867
|
+
type: "boolean",
|
|
1868
|
+
required: false,
|
|
1869
|
+
default: "true",
|
|
1870
|
+
comments: "Whether the webhook is active and delivering events.",
|
|
1871
|
+
clean: _prismatic_io_spectral.util.types.toBool
|
|
1872
|
+
});
|
|
1873
|
+
const webhookAuthType = (0, _prismatic_io_spectral.input)({
|
|
1874
|
+
label: "Authentication Type",
|
|
1875
|
+
type: "string",
|
|
1876
|
+
required: false,
|
|
1877
|
+
default: "NONE",
|
|
1878
|
+
model: [{
|
|
1879
|
+
label: "None",
|
|
1880
|
+
value: "NONE"
|
|
1881
|
+
}, {
|
|
1882
|
+
label: "Header",
|
|
1883
|
+
value: "HEADER"
|
|
1884
|
+
}],
|
|
1885
|
+
comments: "How Jamf Pro authenticates to the destination URL. Header authentication sends a custom header with every event.",
|
|
1886
|
+
clean: _prismatic_io_spectral.util.types.toString
|
|
1887
|
+
});
|
|
1888
|
+
const webhookAuthHeaderName = (0, _prismatic_io_spectral.input)({
|
|
1889
|
+
label: "Auth Header Name",
|
|
1890
|
+
type: "string",
|
|
1891
|
+
required: false,
|
|
1892
|
+
comments: "Name of the header Jamf Pro sends when Authentication Type is Header. Required when using Header authentication.",
|
|
1893
|
+
clean: toOptionalString,
|
|
1894
|
+
placeholder: "X-Jamf-Signature",
|
|
1895
|
+
example: "X-Jamf-Signature"
|
|
1896
|
+
});
|
|
1897
|
+
const webhookAuthHeaderValue = (0, _prismatic_io_spectral.input)({
|
|
1898
|
+
label: "Auth Header Value",
|
|
1899
|
+
type: "string",
|
|
1900
|
+
required: false,
|
|
1901
|
+
comments: "Value of the header Jamf Pro sends when Authentication Type is Header. Required when using Header authentication.",
|
|
1902
|
+
clean: toOptionalString,
|
|
1903
|
+
placeholder: "Enter the header value"
|
|
1904
|
+
});
|
|
1905
|
+
const webhookResourceId = {
|
|
1906
|
+
...resourceId,
|
|
1907
|
+
label: "Webhook",
|
|
1908
|
+
comments: "The unique identifier of the webhook.",
|
|
1909
|
+
dataSource: "selectWebhook"
|
|
1910
|
+
};
|
|
1911
|
+
const createWebhookInputs = {
|
|
1912
|
+
connection,
|
|
1913
|
+
webhookName,
|
|
1914
|
+
webhookEvent,
|
|
1915
|
+
webhookUrl,
|
|
1916
|
+
additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1917
|
+
label: "Additional Fields",
|
|
1918
|
+
required: false,
|
|
1919
|
+
comments: "Additional optional fields: includes Content Type, Enabled, Authentication Type, Auth Header Name, and Auth Header Value.",
|
|
1920
|
+
inputs: {
|
|
1921
|
+
webhookContentType,
|
|
1922
|
+
webhookEnabled,
|
|
1923
|
+
webhookAuthType,
|
|
1924
|
+
webhookAuthHeaderName,
|
|
1925
|
+
webhookAuthHeaderValue
|
|
1926
|
+
}
|
|
1927
|
+
})
|
|
1928
|
+
};
|
|
1929
|
+
const getWebhookInputs = {
|
|
1930
|
+
connection,
|
|
1931
|
+
resourceId: webhookResourceId
|
|
1932
|
+
};
|
|
1933
|
+
const listWebhooksInputs = { connection };
|
|
1934
|
+
const deleteInstancedWebhooksInputs = { connection };
|
|
1935
|
+
const deleteWebhookInputs = {
|
|
1936
|
+
connection,
|
|
1937
|
+
resourceId: webhookResourceId
|
|
1938
|
+
};
|
|
1939
|
+
const updateWebhookInputs = {
|
|
1940
|
+
connection,
|
|
1941
|
+
resourceId: webhookResourceId,
|
|
1942
|
+
additionalFields: (0, _prismatic_io_spectral.structuredObjectInput)({
|
|
1943
|
+
label: "Additional Fields",
|
|
1944
|
+
required: false,
|
|
1945
|
+
comments: "Additional optional fields: includes Name, Event, URL, Content Type, and Enabled.",
|
|
1946
|
+
inputs: {
|
|
1947
|
+
webhookName: {
|
|
1948
|
+
...webhookName,
|
|
1949
|
+
required: false,
|
|
1950
|
+
clean: toOptionalString
|
|
1951
|
+
},
|
|
1952
|
+
webhookEvent: {
|
|
1953
|
+
...webhookEvent,
|
|
1954
|
+
required: false,
|
|
1955
|
+
clean: toOptionalString
|
|
1956
|
+
},
|
|
1957
|
+
webhookUrl: {
|
|
1958
|
+
...webhookUrl,
|
|
1959
|
+
required: false,
|
|
1960
|
+
clean: toOptionalString
|
|
1961
|
+
},
|
|
1962
|
+
webhookContentType: {
|
|
1963
|
+
...webhookContentType,
|
|
1964
|
+
default: void 0,
|
|
1965
|
+
clean: toOptionalString
|
|
1966
|
+
},
|
|
1967
|
+
webhookEnabled: optionalBoolean("Enabled", "Whether the webhook is active and delivering events.")
|
|
1968
|
+
}
|
|
1969
|
+
})
|
|
1970
|
+
};
|
|
1971
|
+
//#endregion
|
|
1972
|
+
//#region src/actions/categories/createCategory.ts
|
|
1973
|
+
const createCategory = (0, _prismatic_io_spectral.action)({
|
|
1974
|
+
display: {
|
|
1975
|
+
label: "Create Category",
|
|
1976
|
+
description: "Create a new category."
|
|
1977
|
+
},
|
|
1978
|
+
inputs: createCategoryInputs,
|
|
1979
|
+
perform: async (context, { connection, categoryName, priority }) => {
|
|
1980
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).post("/v1/categories", {
|
|
1981
|
+
name: categoryName,
|
|
1982
|
+
priority
|
|
1983
|
+
});
|
|
1984
|
+
return { data };
|
|
1985
|
+
},
|
|
1986
|
+
examplePayload: createCategoryExamplePayload
|
|
1987
|
+
});
|
|
1988
|
+
//#endregion
|
|
1989
|
+
//#region src/actions/categories/deleteCategory.ts
|
|
1990
|
+
const deleteCategory = (0, _prismatic_io_spectral.action)({
|
|
1991
|
+
display: {
|
|
1992
|
+
label: "Delete Category",
|
|
1993
|
+
description: "Delete a category by ID."
|
|
1994
|
+
},
|
|
1995
|
+
inputs: deleteCategoryInputs,
|
|
1996
|
+
perform: async (context, { connection, resourceId }) => {
|
|
1997
|
+
await (await createClient(connection, context.debug.enabled)).delete(`/v1/categories/${resourceId}`);
|
|
1998
|
+
return { data: `Successfully deleted category ${resourceId}` };
|
|
1999
|
+
},
|
|
2000
|
+
examplePayload: deleteCategoryExamplePayload
|
|
2001
|
+
});
|
|
2002
|
+
//#endregion
|
|
2003
|
+
//#region src/actions/categories/getCategory.ts
|
|
2004
|
+
const getCategory = (0, _prismatic_io_spectral.action)({
|
|
2005
|
+
display: {
|
|
2006
|
+
label: "Get Category",
|
|
2007
|
+
description: "Get a single category by ID."
|
|
2008
|
+
},
|
|
2009
|
+
inputs: getCategoryInputs,
|
|
2010
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2011
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).get(`/v1/categories/${resourceId}`);
|
|
2012
|
+
return { data };
|
|
2013
|
+
},
|
|
2014
|
+
examplePayload: getCategoryExamplePayload
|
|
2015
|
+
});
|
|
2016
|
+
//#endregion
|
|
2017
|
+
//#region src/actions/categories/listCategories.ts
|
|
2018
|
+
const listCategories = (0, _prismatic_io_spectral.action)({
|
|
2019
|
+
display: {
|
|
2020
|
+
label: "List Categories",
|
|
2021
|
+
description: "List all categories with optional filtering and pagination."
|
|
2022
|
+
},
|
|
2023
|
+
inputs: listCategoriesInputs,
|
|
2024
|
+
perform: async (context, { connection, pagination, sort, filter, fetchAll }) => {
|
|
2025
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v1/categories", fetchAll, {
|
|
2026
|
+
page: pagination.page,
|
|
2027
|
+
"page-size": pagination.pageSize,
|
|
2028
|
+
sort,
|
|
2029
|
+
filter
|
|
2030
|
+
}) };
|
|
2031
|
+
},
|
|
2032
|
+
examplePayload: listCategoriesExamplePayload
|
|
2033
|
+
});
|
|
2034
|
+
//#endregion
|
|
2035
|
+
//#region src/actions/categories/updateCategory.ts
|
|
2036
|
+
const updateCategory = (0, _prismatic_io_spectral.action)({
|
|
2037
|
+
display: {
|
|
2038
|
+
label: "Update Category",
|
|
2039
|
+
description: "Update an existing category."
|
|
2040
|
+
},
|
|
2041
|
+
inputs: updateCategoryInputs,
|
|
2042
|
+
perform: async (context, { connection, resourceId, categoryName, priority }) => {
|
|
2043
|
+
const client = await createClient(connection, context.debug.enabled);
|
|
2044
|
+
const { data: existing } = await client.get(`/v1/categories/${resourceId}`);
|
|
2045
|
+
const { data } = await client.put(`/v1/categories/${resourceId}`, mergeDefined(existing, {
|
|
2046
|
+
name: categoryName,
|
|
2047
|
+
priority
|
|
2048
|
+
}));
|
|
2049
|
+
return { data };
|
|
2050
|
+
},
|
|
2051
|
+
examplePayload: updateCategoryExamplePayload
|
|
2052
|
+
});
|
|
2053
|
+
//#endregion
|
|
2054
|
+
//#region src/actions/categories/index.ts
|
|
2055
|
+
var categories_exports = /* @__PURE__ */ __exportAll({
|
|
2056
|
+
createCategory: () => createCategory,
|
|
2057
|
+
deleteCategory: () => deleteCategory,
|
|
2058
|
+
getCategory: () => getCategory,
|
|
2059
|
+
listCategories: () => listCategories,
|
|
2060
|
+
updateCategory: () => updateCategory
|
|
2061
|
+
});
|
|
2062
|
+
//#endregion
|
|
2063
|
+
//#region src/actions/computers/getComputer.ts
|
|
2064
|
+
const getComputer = (0, _prismatic_io_spectral.action)({
|
|
2065
|
+
display: {
|
|
2066
|
+
label: "Get Computer",
|
|
2067
|
+
description: "Get a single computer inventory record by ID."
|
|
2068
|
+
},
|
|
2069
|
+
inputs: getComputerInputs,
|
|
2070
|
+
perform: async (context, { connection, resourceId, section }) => {
|
|
2071
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).get(`/v3/computers-inventory/${resourceId}`, {
|
|
2072
|
+
params: { section },
|
|
2073
|
+
paramsSerializer: { indexes: null }
|
|
2074
|
+
});
|
|
2075
|
+
return { data };
|
|
2076
|
+
},
|
|
2077
|
+
examplePayload: getComputerExamplePayload
|
|
2078
|
+
});
|
|
2079
|
+
//#endregion
|
|
2080
|
+
//#region src/actions/computers/listComputers.ts
|
|
2081
|
+
const listComputers = (0, _prismatic_io_spectral.action)({
|
|
2082
|
+
display: {
|
|
2083
|
+
label: "List Computers",
|
|
2084
|
+
description: "List computer inventory records with optional filtering and pagination."
|
|
2085
|
+
},
|
|
2086
|
+
inputs: listComputersInputs,
|
|
2087
|
+
perform: async (context, { connection, pagination, sort, filter, section, fetchAll }) => {
|
|
2088
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v3/computers-inventory", fetchAll, {
|
|
2089
|
+
page: pagination.page,
|
|
2090
|
+
"page-size": pagination.pageSize,
|
|
2091
|
+
sort,
|
|
2092
|
+
filter,
|
|
2093
|
+
section
|
|
2094
|
+
}) };
|
|
2095
|
+
},
|
|
2096
|
+
examplePayload: listComputersExamplePayload
|
|
2097
|
+
});
|
|
2098
|
+
//#endregion
|
|
2099
|
+
//#region src/actions/computers/updateComputer.ts
|
|
2100
|
+
const updateComputer = (0, _prismatic_io_spectral.action)({
|
|
2101
|
+
display: {
|
|
2102
|
+
label: "Update Computer",
|
|
2103
|
+
description: "Update specific fields of a computer inventory record. Only the provided fields are modified."
|
|
2104
|
+
},
|
|
2105
|
+
inputs: updateComputerInputs,
|
|
2106
|
+
perform: async (context, { connection, resourceId, computerUpdateBody }) => {
|
|
2107
|
+
await (await createClient(connection, context.debug.enabled)).patch(`/v3/computers-inventory-detail/${resourceId}`, computerUpdateBody);
|
|
2108
|
+
return { data: `Successfully updated computer ${resourceId}` };
|
|
2109
|
+
},
|
|
2110
|
+
examplePayload: updateComputerExamplePayload
|
|
2111
|
+
});
|
|
2112
|
+
//#endregion
|
|
2113
|
+
//#region src/actions/computers/index.ts
|
|
2114
|
+
var computers_exports = /* @__PURE__ */ __exportAll({
|
|
2115
|
+
getComputer: () => getComputer,
|
|
2116
|
+
listComputers: () => listComputers,
|
|
2117
|
+
updateComputer: () => updateComputer
|
|
2118
|
+
});
|
|
2119
|
+
//#endregion
|
|
2120
|
+
//#region src/actions/departments/createDepartment.ts
|
|
2121
|
+
const createDepartment = (0, _prismatic_io_spectral.action)({
|
|
2122
|
+
display: {
|
|
2123
|
+
label: "Create Department",
|
|
2124
|
+
description: "Create a new department."
|
|
2125
|
+
},
|
|
2126
|
+
inputs: createDepartmentInputs,
|
|
2127
|
+
perform: async (context, { connection, departmentName }) => {
|
|
2128
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).post("/v1/departments", { name: departmentName });
|
|
2129
|
+
return { data };
|
|
2130
|
+
},
|
|
2131
|
+
examplePayload: createDepartmentExamplePayload
|
|
2132
|
+
});
|
|
2133
|
+
//#endregion
|
|
2134
|
+
//#region src/actions/departments/deleteDepartment.ts
|
|
2135
|
+
const deleteDepartment = (0, _prismatic_io_spectral.action)({
|
|
2136
|
+
display: {
|
|
2137
|
+
label: "Delete Department",
|
|
2138
|
+
description: "Delete a department by ID."
|
|
2139
|
+
},
|
|
2140
|
+
inputs: deleteDepartmentInputs,
|
|
2141
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2142
|
+
await (await createClient(connection, context.debug.enabled)).delete(`/v1/departments/${resourceId}`);
|
|
2143
|
+
return { data: `Successfully deleted department ${resourceId}` };
|
|
2144
|
+
},
|
|
2145
|
+
examplePayload: deleteDepartmentExamplePayload
|
|
2146
|
+
});
|
|
2147
|
+
//#endregion
|
|
2148
|
+
//#region src/actions/departments/getDepartment.ts
|
|
2149
|
+
const getDepartment = (0, _prismatic_io_spectral.action)({
|
|
2150
|
+
display: {
|
|
2151
|
+
label: "Get Department",
|
|
2152
|
+
description: "Get a single department by ID."
|
|
2153
|
+
},
|
|
2154
|
+
inputs: getDepartmentInputs,
|
|
2155
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2156
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).get(`/v1/departments/${resourceId}`);
|
|
2157
|
+
return { data };
|
|
2158
|
+
},
|
|
2159
|
+
examplePayload: getDepartmentExamplePayload
|
|
2160
|
+
});
|
|
2161
|
+
//#endregion
|
|
2162
|
+
//#region src/actions/departments/listDepartments.ts
|
|
2163
|
+
const listDepartments = (0, _prismatic_io_spectral.action)({
|
|
2164
|
+
display: {
|
|
2165
|
+
label: "List Departments",
|
|
2166
|
+
description: "List all departments with optional filtering and pagination."
|
|
2167
|
+
},
|
|
2168
|
+
inputs: listDepartmentsInputs,
|
|
2169
|
+
perform: async (context, { connection, pagination, sort, filter, fetchAll }) => {
|
|
2170
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v1/departments", fetchAll, {
|
|
2171
|
+
page: pagination.page,
|
|
2172
|
+
"page-size": pagination.pageSize,
|
|
2173
|
+
sort,
|
|
2174
|
+
filter
|
|
2175
|
+
}) };
|
|
2176
|
+
},
|
|
2177
|
+
examplePayload: listDepartmentsExamplePayload
|
|
2178
|
+
});
|
|
2179
|
+
//#endregion
|
|
2180
|
+
//#region src/actions/departments/updateDepartment.ts
|
|
2181
|
+
const updateDepartment = (0, _prismatic_io_spectral.action)({
|
|
2182
|
+
display: {
|
|
2183
|
+
label: "Update Department",
|
|
2184
|
+
description: "Update an existing department."
|
|
2185
|
+
},
|
|
2186
|
+
inputs: updateDepartmentInputs,
|
|
2187
|
+
perform: async (context, { connection, resourceId, departmentName }) => {
|
|
2188
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).put(`/v1/departments/${resourceId}`, { name: departmentName });
|
|
2189
|
+
return { data };
|
|
2190
|
+
},
|
|
2191
|
+
examplePayload: updateDepartmentExamplePayload
|
|
2192
|
+
});
|
|
2193
|
+
//#endregion
|
|
2194
|
+
//#region src/actions/departments/index.ts
|
|
2195
|
+
var departments_exports = /* @__PURE__ */ __exportAll({
|
|
2196
|
+
createDepartment: () => createDepartment,
|
|
2197
|
+
deleteDepartment: () => deleteDepartment,
|
|
2198
|
+
getDepartment: () => getDepartment,
|
|
2199
|
+
listDepartments: () => listDepartments,
|
|
2200
|
+
updateDepartment: () => updateDepartment
|
|
2201
|
+
});
|
|
2202
|
+
//#endregion
|
|
2203
|
+
//#region src/actions/misc/rawRequest.ts
|
|
2204
|
+
const rawRequest = (0, _prismatic_io_spectral.action)({
|
|
2205
|
+
display: {
|
|
2206
|
+
label: "Raw Request",
|
|
2207
|
+
description: "Send a raw HTTP request to the Jamf Pro API or the Classic API."
|
|
2208
|
+
},
|
|
2209
|
+
inputs: rawRequestInputs,
|
|
2210
|
+
perform: async (context, { connection, apiType, ...httpInputs }) => {
|
|
2211
|
+
const client = await createClient(connection, context.debug.enabled);
|
|
2212
|
+
const { data } = await (0, _prismatic_io_spectral_http.sendRawRequest)(`${getBaseUrl(connection)}/${apiType}`, {
|
|
2213
|
+
...httpInputs,
|
|
2214
|
+
debugRequest: context.debug.enabled
|
|
2215
|
+
}, client.defaults?.headers ?? {});
|
|
2216
|
+
return { data };
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
//#endregion
|
|
2220
|
+
//#region src/actions/misc/index.ts
|
|
2221
|
+
var misc_exports = /* @__PURE__ */ __exportAll({ rawRequest: () => rawRequest });
|
|
2222
|
+
//#endregion
|
|
2223
|
+
//#region src/actions/mobileDevices/getMobileDevice.ts
|
|
2224
|
+
const getMobileDevice = (0, _prismatic_io_spectral.action)({
|
|
2225
|
+
display: {
|
|
2226
|
+
label: "Get Mobile Device",
|
|
2227
|
+
description: "Get a single mobile device record by ID."
|
|
2228
|
+
},
|
|
2229
|
+
inputs: getMobileDeviceInputs,
|
|
2230
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2231
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).get(`/v2/mobile-devices/${resourceId}`);
|
|
2232
|
+
return { data };
|
|
2233
|
+
},
|
|
2234
|
+
examplePayload: getMobileDeviceExamplePayload
|
|
2235
|
+
});
|
|
2236
|
+
//#endregion
|
|
2237
|
+
//#region src/actions/mobileDevices/listMobileDevices.ts
|
|
2238
|
+
const listMobileDevices = (0, _prismatic_io_spectral.action)({
|
|
2239
|
+
display: {
|
|
2240
|
+
label: "List Mobile Devices",
|
|
2241
|
+
description: "List mobile device inventory records with optional filtering and pagination."
|
|
2242
|
+
},
|
|
2243
|
+
inputs: listMobileDevicesInputs,
|
|
2244
|
+
perform: async (context, { connection, pagination, sort, filter, section, fetchAll }) => {
|
|
2245
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v2/mobile-devices/detail", fetchAll, {
|
|
2246
|
+
page: pagination.page,
|
|
2247
|
+
"page-size": pagination.pageSize,
|
|
2248
|
+
sort,
|
|
2249
|
+
filter,
|
|
2250
|
+
section
|
|
2251
|
+
}) };
|
|
2252
|
+
},
|
|
2253
|
+
examplePayload: listMobileDevicesExamplePayload
|
|
2254
|
+
});
|
|
2255
|
+
//#endregion
|
|
2256
|
+
//#region src/actions/mobileDevices/index.ts
|
|
2257
|
+
var mobileDevices_exports = /* @__PURE__ */ __exportAll({
|
|
2258
|
+
getMobileDevice: () => getMobileDevice,
|
|
2259
|
+
listMobileDevices: () => listMobileDevices
|
|
2260
|
+
});
|
|
2261
|
+
//#endregion
|
|
2262
|
+
//#region src/actions/packages/createPackage.ts
|
|
2263
|
+
const createPackage = (0, _prismatic_io_spectral.action)({
|
|
2264
|
+
display: {
|
|
2265
|
+
label: "Create Package",
|
|
2266
|
+
description: "Create a new package record in Jamf Pro."
|
|
2267
|
+
},
|
|
2268
|
+
inputs: createPackageInputs,
|
|
2269
|
+
perform: async (context, { connection, packageName, packageFileName, packageCategoryId, additionalFields }) => {
|
|
2270
|
+
const { packagePriority, packageInfo, packageNotes, packageRebootRequired, packageOsInstall, packageFillUserTemplate, packageSuppressUpdates, packageSuppressEula, packageSuppressFromDock, packageSuppressRegistration } = additionalFields;
|
|
2271
|
+
const client = await createClient(connection, context.debug.enabled);
|
|
2272
|
+
const body = {
|
|
2273
|
+
packageName,
|
|
2274
|
+
fileName: packageFileName,
|
|
2275
|
+
categoryId: packageCategoryId ?? "-1",
|
|
2276
|
+
priority: packagePriority ? packagePriority : 10,
|
|
2277
|
+
rebootRequired: packageRebootRequired,
|
|
2278
|
+
osInstall: packageOsInstall,
|
|
2279
|
+
fillUserTemplate: packageFillUserTemplate,
|
|
2280
|
+
suppressUpdates: packageSuppressUpdates,
|
|
2281
|
+
suppressEula: packageSuppressEula,
|
|
2282
|
+
suppressFromDock: packageSuppressFromDock,
|
|
2283
|
+
suppressRegistration: packageSuppressRegistration,
|
|
2284
|
+
info: packageInfo,
|
|
2285
|
+
notes: packageNotes
|
|
2286
|
+
};
|
|
2287
|
+
const { data } = await client.post("/v1/packages", body);
|
|
2288
|
+
return { data };
|
|
2289
|
+
},
|
|
2290
|
+
examplePayload: createPackageExamplePayload
|
|
2291
|
+
});
|
|
2292
|
+
//#endregion
|
|
2293
|
+
//#region src/actions/packages/deletePackage.ts
|
|
2294
|
+
const deletePackage = (0, _prismatic_io_spectral.action)({
|
|
2295
|
+
display: {
|
|
2296
|
+
label: "Delete Package",
|
|
2297
|
+
description: "Delete a package record by ID."
|
|
2298
|
+
},
|
|
2299
|
+
inputs: deletePackageInputs,
|
|
2300
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2301
|
+
await (await createClient(connection, context.debug.enabled)).delete(`/v1/packages/${resourceId}`);
|
|
2302
|
+
return { data: `Successfully deleted package ${resourceId}` };
|
|
2303
|
+
},
|
|
2304
|
+
examplePayload: deletePackageExamplePayload
|
|
2305
|
+
});
|
|
2306
|
+
//#endregion
|
|
2307
|
+
//#region src/actions/packages/getPackage.ts
|
|
2308
|
+
const getPackage = (0, _prismatic_io_spectral.action)({
|
|
2309
|
+
display: {
|
|
2310
|
+
label: "Get Package",
|
|
2311
|
+
description: "Get a single package record by ID."
|
|
2312
|
+
},
|
|
2313
|
+
inputs: getPackageInputs,
|
|
2314
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2315
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).get(`/v1/packages/${resourceId}`);
|
|
2316
|
+
return { data };
|
|
2317
|
+
},
|
|
2318
|
+
examplePayload: getPackageExamplePayload
|
|
2319
|
+
});
|
|
2320
|
+
//#endregion
|
|
2321
|
+
//#region src/actions/packages/listPackages.ts
|
|
2322
|
+
const listPackages = (0, _prismatic_io_spectral.action)({
|
|
2323
|
+
display: {
|
|
2324
|
+
label: "List Packages",
|
|
2325
|
+
description: "List all packages with optional filtering and pagination."
|
|
2326
|
+
},
|
|
2327
|
+
inputs: listPackagesInputs,
|
|
2328
|
+
perform: async (context, { connection, pagination, sort, filter, fetchAll }) => {
|
|
2329
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v1/packages", fetchAll, {
|
|
2330
|
+
page: pagination.page,
|
|
2331
|
+
"page-size": pagination.pageSize,
|
|
2332
|
+
sort,
|
|
2333
|
+
filter
|
|
2334
|
+
}) };
|
|
2335
|
+
},
|
|
2336
|
+
examplePayload: listPackagesExamplePayload
|
|
2337
|
+
});
|
|
2338
|
+
//#endregion
|
|
2339
|
+
//#region src/actions/packages/updatePackage.ts
|
|
2340
|
+
const updatePackage = (0, _prismatic_io_spectral.action)({
|
|
2341
|
+
display: {
|
|
2342
|
+
label: "Update Package",
|
|
2343
|
+
description: "Update an existing package record."
|
|
2344
|
+
},
|
|
2345
|
+
inputs: updatePackageInputs,
|
|
2346
|
+
perform: async (context, { connection, resourceId, packageCategoryId, additionalFields }) => {
|
|
2347
|
+
const { packageName, packageFileName, packagePriority, packageInfo, packageNotes, packageRebootRequired, packageOsInstall, packageFillUserTemplate, packageSuppressUpdates, packageSuppressEula, packageSuppressFromDock, packageSuppressRegistration } = additionalFields;
|
|
2348
|
+
const client = await createClient(connection, context.debug.enabled);
|
|
2349
|
+
const { data: existing } = await client.get(`/v1/packages/${resourceId}`);
|
|
2350
|
+
const body = mergeDefined(existing, {
|
|
2351
|
+
packageName,
|
|
2352
|
+
fileName: packageFileName,
|
|
2353
|
+
categoryId: packageCategoryId,
|
|
2354
|
+
priority: packagePriority,
|
|
2355
|
+
rebootRequired: packageRebootRequired,
|
|
2356
|
+
osInstall: packageOsInstall,
|
|
2357
|
+
fillUserTemplate: packageFillUserTemplate,
|
|
2358
|
+
suppressUpdates: packageSuppressUpdates,
|
|
2359
|
+
suppressEula: packageSuppressEula,
|
|
2360
|
+
suppressFromDock: packageSuppressFromDock,
|
|
2361
|
+
suppressRegistration: packageSuppressRegistration,
|
|
2362
|
+
info: packageInfo,
|
|
2363
|
+
notes: packageNotes
|
|
2364
|
+
});
|
|
2365
|
+
const { data } = await client.put(`/v1/packages/${resourceId}`, body);
|
|
2366
|
+
return { data };
|
|
2367
|
+
},
|
|
2368
|
+
examplePayload: updatePackageExamplePayload
|
|
2369
|
+
});
|
|
2370
|
+
//#endregion
|
|
2371
|
+
//#region src/actions/packages/index.ts
|
|
2372
|
+
var packages_exports = /* @__PURE__ */ __exportAll({
|
|
2373
|
+
createPackage: () => createPackage,
|
|
2374
|
+
deletePackage: () => deletePackage,
|
|
2375
|
+
getPackage: () => getPackage,
|
|
2376
|
+
listPackages: () => listPackages,
|
|
2377
|
+
updatePackage: () => updatePackage
|
|
2378
|
+
});
|
|
2379
|
+
//#endregion
|
|
2380
|
+
//#region src/actions/scripts/createScript.ts
|
|
2381
|
+
const createScript = (0, _prismatic_io_spectral.action)({
|
|
2382
|
+
display: {
|
|
2383
|
+
label: "Create Script",
|
|
2384
|
+
description: "Create a new script."
|
|
2385
|
+
},
|
|
2386
|
+
inputs: createScriptInputs,
|
|
2387
|
+
perform: async (context, { connection, scriptName, scriptCategoryId, additionalFields }) => {
|
|
2388
|
+
const { scriptContents, scriptPriority, scriptInfo, scriptNotes } = additionalFields;
|
|
2389
|
+
const client = await createClient(connection, context.debug.enabled);
|
|
2390
|
+
const body = {
|
|
2391
|
+
name: scriptName,
|
|
2392
|
+
scriptContents,
|
|
2393
|
+
categoryId: scriptCategoryId,
|
|
2394
|
+
priority: scriptPriority,
|
|
2395
|
+
info: scriptInfo,
|
|
2396
|
+
notes: scriptNotes
|
|
2397
|
+
};
|
|
2398
|
+
const { data } = await client.post("/v1/scripts", body);
|
|
2399
|
+
return { data };
|
|
2400
|
+
},
|
|
2401
|
+
examplePayload: createScriptExamplePayload
|
|
2402
|
+
});
|
|
2403
|
+
//#endregion
|
|
2404
|
+
//#region src/actions/scripts/deleteScript.ts
|
|
2405
|
+
const deleteScript = (0, _prismatic_io_spectral.action)({
|
|
2406
|
+
display: {
|
|
2407
|
+
label: "Delete Script",
|
|
2408
|
+
description: "Delete a script by ID."
|
|
2409
|
+
},
|
|
2410
|
+
inputs: deleteScriptInputs,
|
|
2411
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2412
|
+
await (await createClient(connection, context.debug.enabled)).delete(`/v1/scripts/${resourceId}`);
|
|
2413
|
+
return { data: `Successfully deleted script ${resourceId}` };
|
|
2414
|
+
},
|
|
2415
|
+
examplePayload: deleteScriptExamplePayload
|
|
2416
|
+
});
|
|
2417
|
+
//#endregion
|
|
2418
|
+
//#region src/actions/scripts/getScript.ts
|
|
2419
|
+
const getScript = (0, _prismatic_io_spectral.action)({
|
|
2420
|
+
display: {
|
|
2421
|
+
label: "Get Script",
|
|
2422
|
+
description: "Get a single script by ID."
|
|
2423
|
+
},
|
|
2424
|
+
inputs: getScriptInputs,
|
|
2425
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2426
|
+
const { data } = await (await createClient(connection, context.debug.enabled)).get(`/v1/scripts/${resourceId}`);
|
|
2427
|
+
return { data };
|
|
2428
|
+
},
|
|
2429
|
+
examplePayload: getScriptExamplePayload
|
|
2430
|
+
});
|
|
2431
|
+
//#endregion
|
|
2432
|
+
//#region src/actions/scripts/listScripts.ts
|
|
2433
|
+
const listScripts = (0, _prismatic_io_spectral.action)({
|
|
2434
|
+
display: {
|
|
2435
|
+
label: "List Scripts",
|
|
2436
|
+
description: "List all scripts with optional filtering and pagination."
|
|
2437
|
+
},
|
|
2438
|
+
inputs: listScriptsInputs,
|
|
2439
|
+
perform: async (context, { connection, pagination, sort, filter, fetchAll }) => {
|
|
2440
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v1/scripts", fetchAll, {
|
|
2441
|
+
page: pagination.page,
|
|
2442
|
+
"page-size": pagination.pageSize,
|
|
2443
|
+
sort,
|
|
2444
|
+
filter
|
|
2445
|
+
}) };
|
|
2446
|
+
},
|
|
2447
|
+
examplePayload: listScriptsExamplePayload
|
|
2448
|
+
});
|
|
2449
|
+
//#endregion
|
|
2450
|
+
//#region src/actions/scripts/updateScript.ts
|
|
2451
|
+
const updateScript = (0, _prismatic_io_spectral.action)({
|
|
2452
|
+
display: {
|
|
2453
|
+
label: "Update Script",
|
|
2454
|
+
description: "Update an existing script."
|
|
2455
|
+
},
|
|
2456
|
+
inputs: updateScriptInputs,
|
|
2457
|
+
perform: async (context, { connection, resourceId, scriptCategoryId, additionalFields }) => {
|
|
2458
|
+
const { scriptName, scriptContents, scriptPriority, scriptInfo, scriptNotes } = additionalFields;
|
|
2459
|
+
const client = await createClient(connection, context.debug.enabled);
|
|
2460
|
+
const { data: existing } = await client.get(`/v1/scripts/${resourceId}`);
|
|
2461
|
+
const body = mergeDefined(existing, {
|
|
2462
|
+
name: scriptName,
|
|
2463
|
+
scriptContents,
|
|
2464
|
+
categoryId: scriptCategoryId,
|
|
2465
|
+
priority: scriptPriority,
|
|
2466
|
+
info: scriptInfo,
|
|
2467
|
+
notes: scriptNotes
|
|
2468
|
+
});
|
|
2469
|
+
const { data } = await client.put(`/v1/scripts/${resourceId}`, body);
|
|
2470
|
+
return { data };
|
|
2471
|
+
},
|
|
2472
|
+
examplePayload: updateScriptExamplePayload
|
|
2473
|
+
});
|
|
2474
|
+
//#endregion
|
|
2475
|
+
//#region src/actions/scripts/index.ts
|
|
2476
|
+
var scripts_exports = /* @__PURE__ */ __exportAll({
|
|
2477
|
+
createScript: () => createScript,
|
|
2478
|
+
deleteScript: () => deleteScript,
|
|
2479
|
+
getScript: () => getScript,
|
|
2480
|
+
listScripts: () => listScripts,
|
|
2481
|
+
updateScript: () => updateScript
|
|
2482
|
+
});
|
|
2483
|
+
//#endregion
|
|
2484
|
+
//#region src/actions/users/listUsers.ts
|
|
2485
|
+
const listUsers = (0, _prismatic_io_spectral.action)({
|
|
2486
|
+
display: {
|
|
2487
|
+
label: "List Users",
|
|
2488
|
+
description: "List Jamf Pro user accounts with optional filtering and pagination."
|
|
2489
|
+
},
|
|
2490
|
+
inputs: listUsersInputs,
|
|
2491
|
+
perform: async (context, { connection, pagination, sort, filter, fetchAll }) => {
|
|
2492
|
+
return { data: await paginateResults(await createClient(connection, context.debug.enabled), "/v1/users", fetchAll, {
|
|
2493
|
+
page: pagination.page,
|
|
2494
|
+
"page-size": pagination.pageSize,
|
|
2495
|
+
sort,
|
|
2496
|
+
filter
|
|
2497
|
+
}) };
|
|
2498
|
+
},
|
|
2499
|
+
examplePayload: listUsersExamplePayload
|
|
2500
|
+
});
|
|
2501
|
+
//#endregion
|
|
2502
|
+
//#region src/actions/users/index.ts
|
|
2503
|
+
var users_exports = /* @__PURE__ */ __exportAll({ listUsers: () => listUsers });
|
|
2504
|
+
//#endregion
|
|
2505
|
+
//#region src/actions/webhooks/createWebhook.ts
|
|
2506
|
+
const createWebhook = (0, _prismatic_io_spectral.action)({
|
|
2507
|
+
display: {
|
|
2508
|
+
label: "Create Webhook",
|
|
2509
|
+
description: "Create a new webhook subscription in Jamf Pro."
|
|
2510
|
+
},
|
|
2511
|
+
inputs: createWebhookInputs,
|
|
2512
|
+
perform: async (context, { connection, webhookName, webhookEvent, webhookUrl, additionalFields }) => {
|
|
2513
|
+
const { webhookContentType, webhookEnabled, webhookAuthType, webhookAuthHeaderName, webhookAuthHeaderValue } = additionalFields;
|
|
2514
|
+
const client = await createClassicClient(connection, context.debug.enabled);
|
|
2515
|
+
let authFields = {};
|
|
2516
|
+
if (webhookAuthType === "HEADER") {
|
|
2517
|
+
if (!webhookAuthHeaderName || !webhookAuthHeaderValue) throw new Error("Header authentication requires both an Auth Header Name and an Auth Header Value.");
|
|
2518
|
+
authFields = {
|
|
2519
|
+
authentication_type: "HEADER",
|
|
2520
|
+
header: JSON.stringify({ [webhookAuthHeaderName]: webhookAuthHeaderValue })
|
|
2521
|
+
};
|
|
2522
|
+
}
|
|
2523
|
+
const body = toWebhookXml({
|
|
2524
|
+
name: webhookName,
|
|
2525
|
+
event: webhookEvent,
|
|
2526
|
+
url: webhookUrl,
|
|
2527
|
+
content_type: webhookContentType,
|
|
2528
|
+
enabled: webhookEnabled,
|
|
2529
|
+
...authFields
|
|
2530
|
+
});
|
|
2531
|
+
const { data } = await client.post("/webhooks/id/0", body, { headers: { "Content-Type": "application/xml" } });
|
|
2532
|
+
return { data: { id: parseWebhookId(data) ?? null } };
|
|
2533
|
+
},
|
|
2534
|
+
examplePayload: createWebhookExamplePayload
|
|
2535
|
+
});
|
|
2536
|
+
//#endregion
|
|
2537
|
+
//#region src/actions/webhooks/deleteInstancedWebhooks.ts
|
|
2538
|
+
const deleteInstancedWebhooks = (0, _prismatic_io_spectral.action)({
|
|
2539
|
+
display: {
|
|
2540
|
+
label: "Delete Instanced Webhooks",
|
|
2541
|
+
description: "Delete all Jamf Pro webhooks that point to a flow in this instance."
|
|
2542
|
+
},
|
|
2543
|
+
inputs: deleteInstancedWebhooksInputs,
|
|
2544
|
+
perform: async (context, { connection }) => {
|
|
2545
|
+
const client = await createClassicClient(connection, context.debug.enabled);
|
|
2546
|
+
const { data } = await client.get("/webhooks");
|
|
2547
|
+
const webhooks = await Promise.all(data.webhooks.map(({ id }) => client.get(`/webhooks/id/${id}`).then((response) => response.data.webhook)));
|
|
2548
|
+
const instanceUrls = Object.values(context.webhookUrls);
|
|
2549
|
+
const toDelete = webhooks.filter((webhook) => instanceUrls.includes(webhook.url));
|
|
2550
|
+
for (const webhook of toDelete) {
|
|
2551
|
+
context.logger.info(`Deleting webhook ${webhook.id}...`);
|
|
2552
|
+
await client.delete(`/webhooks/id/${webhook.id}`);
|
|
2553
|
+
}
|
|
2554
|
+
return { data: { webhooksDeleted: toDelete.length } };
|
|
2555
|
+
},
|
|
2556
|
+
examplePayload: deleteInstancedWebhooksExamplePayload
|
|
2557
|
+
});
|
|
2558
|
+
//#endregion
|
|
2559
|
+
//#region src/actions/webhooks/deleteWebhook.ts
|
|
2560
|
+
const deleteWebhook = (0, _prismatic_io_spectral.action)({
|
|
2561
|
+
display: {
|
|
2562
|
+
label: "Delete Webhook",
|
|
2563
|
+
description: "Delete a webhook subscription by ID."
|
|
2564
|
+
},
|
|
2565
|
+
inputs: deleteWebhookInputs,
|
|
2566
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2567
|
+
await (await createClassicClient(connection, context.debug.enabled)).delete(`/webhooks/id/${resourceId}`);
|
|
2568
|
+
return { data: `Successfully deleted webhook ${resourceId}` };
|
|
2569
|
+
},
|
|
2570
|
+
examplePayload: deleteWebhookExamplePayload
|
|
2571
|
+
});
|
|
2572
|
+
//#endregion
|
|
2573
|
+
//#region src/actions/webhooks/getWebhook.ts
|
|
2574
|
+
const getWebhook = (0, _prismatic_io_spectral.action)({
|
|
2575
|
+
display: {
|
|
2576
|
+
label: "Get Webhook",
|
|
2577
|
+
description: "Get a single webhook subscription by ID."
|
|
2578
|
+
},
|
|
2579
|
+
inputs: getWebhookInputs,
|
|
2580
|
+
perform: async (context, { connection, resourceId }) => {
|
|
2581
|
+
const { data } = await (await createClassicClient(connection, context.debug.enabled)).get(`/webhooks/id/${resourceId}`);
|
|
2582
|
+
return { data };
|
|
2583
|
+
},
|
|
2584
|
+
examplePayload: getWebhookExamplePayload
|
|
2585
|
+
});
|
|
2586
|
+
//#endregion
|
|
2587
|
+
//#region src/actions/webhooks/listWebhooks.ts
|
|
2588
|
+
const listWebhooks = (0, _prismatic_io_spectral.action)({
|
|
2589
|
+
display: {
|
|
2590
|
+
label: "List Webhooks",
|
|
2591
|
+
description: "List all webhook subscriptions configured in Jamf Pro."
|
|
2592
|
+
},
|
|
2593
|
+
inputs: listWebhooksInputs,
|
|
2594
|
+
perform: async (context, { connection }) => {
|
|
2595
|
+
const { data } = await (await createClassicClient(connection, context.debug.enabled)).get("/webhooks");
|
|
2596
|
+
return { data };
|
|
2597
|
+
},
|
|
2598
|
+
examplePayload: listWebhooksExamplePayload
|
|
2599
|
+
});
|
|
2600
|
+
//#endregion
|
|
2601
|
+
//#region src/actions/webhooks/updateWebhook.ts
|
|
2602
|
+
const updateWebhook = (0, _prismatic_io_spectral.action)({
|
|
2603
|
+
display: {
|
|
2604
|
+
label: "Update Webhook",
|
|
2605
|
+
description: "Update an existing webhook subscription."
|
|
2606
|
+
},
|
|
2607
|
+
inputs: updateWebhookInputs,
|
|
2608
|
+
perform: async (context, { connection, resourceId, additionalFields }) => {
|
|
2609
|
+
const { webhookName, webhookEvent, webhookUrl, webhookContentType, webhookEnabled } = additionalFields;
|
|
2610
|
+
const client = await createClassicClient(connection, context.debug.enabled);
|
|
2611
|
+
const body = toWebhookXml({
|
|
2612
|
+
name: webhookName,
|
|
2613
|
+
event: webhookEvent,
|
|
2614
|
+
url: webhookUrl,
|
|
2615
|
+
content_type: webhookContentType,
|
|
2616
|
+
enabled: webhookEnabled
|
|
2617
|
+
});
|
|
2618
|
+
await client.put(`/webhooks/id/${resourceId}`, body, { headers: { "Content-Type": "application/xml" } });
|
|
2619
|
+
return { data: { id: Number(resourceId) } };
|
|
2620
|
+
},
|
|
2621
|
+
examplePayload: updateWebhookExamplePayload
|
|
2622
|
+
});
|
|
2623
|
+
//#endregion
|
|
2624
|
+
//#region src/actions/webhooks/index.ts
|
|
2625
|
+
var webhooks_exports = /* @__PURE__ */ __exportAll({
|
|
2626
|
+
createWebhook: () => createWebhook,
|
|
2627
|
+
deleteInstancedWebhooks: () => deleteInstancedWebhooks,
|
|
2628
|
+
deleteWebhook: () => deleteWebhook,
|
|
2629
|
+
getWebhook: () => getWebhook,
|
|
2630
|
+
listWebhooks: () => listWebhooks,
|
|
2631
|
+
updateWebhook: () => updateWebhook
|
|
2632
|
+
});
|
|
2633
|
+
//#endregion
|
|
2634
|
+
//#region src/actions/index.ts
|
|
2635
|
+
var actions_default = {
|
|
2636
|
+
...computers_exports,
|
|
2637
|
+
...mobileDevices_exports,
|
|
2638
|
+
...users_exports,
|
|
2639
|
+
...departments_exports,
|
|
2640
|
+
...categories_exports,
|
|
2641
|
+
...scripts_exports,
|
|
2642
|
+
...packages_exports,
|
|
2643
|
+
...webhooks_exports,
|
|
2644
|
+
...misc_exports
|
|
2645
|
+
};
|
|
2646
|
+
//#endregion
|
|
2647
|
+
//#region src/dataSources/selectCategory.ts
|
|
2648
|
+
const selectCategory = (0, _prismatic_io_spectral.dataSource)({
|
|
2649
|
+
display: {
|
|
2650
|
+
label: "Select Category",
|
|
2651
|
+
description: "Dynamically fetch a list of categories from Jamf Pro for use in a dropdown."
|
|
2652
|
+
},
|
|
2653
|
+
dataSourceType: "picklist",
|
|
2654
|
+
inputs: selectCategoryInputs,
|
|
2655
|
+
perform: async (_context, { connection }) => {
|
|
2656
|
+
const { results } = await paginateResults(await createClient(connection, false), "/v1/categories", true, {});
|
|
2657
|
+
return { result: mapToSortedElements(results, "id", "name") };
|
|
2658
|
+
},
|
|
2659
|
+
examplePayload: selectCategoryExamplePayload
|
|
2660
|
+
});
|
|
2661
|
+
//#endregion
|
|
2662
|
+
//#region src/dataSources/selectComputer.ts
|
|
2663
|
+
const selectComputer = (0, _prismatic_io_spectral.dataSource)({
|
|
2664
|
+
display: {
|
|
2665
|
+
label: "Select Computer",
|
|
2666
|
+
description: "Dynamically fetch a list of computers from Jamf Pro for use in a dropdown."
|
|
2667
|
+
},
|
|
2668
|
+
dataSourceType: "picklist",
|
|
2669
|
+
inputs: selectComputerInputs,
|
|
2670
|
+
perform: async (_context, { connection }) => {
|
|
2671
|
+
const { results } = await paginateResults(await createClient(connection, false), "/v1/computers-inventory", true, { section: ["GENERAL"] });
|
|
2672
|
+
return { result: mapToSortedElements(results, "id", (c) => c.general?.name) };
|
|
2673
|
+
},
|
|
2674
|
+
examplePayload: selectComputerExamplePayload
|
|
2675
|
+
});
|
|
2676
|
+
//#endregion
|
|
2677
|
+
//#region src/dataSources/selectDepartment.ts
|
|
2678
|
+
const selectDepartment = (0, _prismatic_io_spectral.dataSource)({
|
|
2679
|
+
display: {
|
|
2680
|
+
label: "Select Department",
|
|
2681
|
+
description: "Dynamically fetch a list of departments from Jamf Pro for use in a dropdown."
|
|
2682
|
+
},
|
|
2683
|
+
dataSourceType: "picklist",
|
|
2684
|
+
inputs: selectDepartmentInputs,
|
|
2685
|
+
perform: async (_context, { connection }) => {
|
|
2686
|
+
const { results } = await paginateResults(await createClient(connection, false), "/v1/departments", true, {});
|
|
2687
|
+
return { result: mapToSortedElements(results, "id", "name") };
|
|
2688
|
+
},
|
|
2689
|
+
examplePayload: selectDepartmentExamplePayload
|
|
2690
|
+
});
|
|
2691
|
+
//#endregion
|
|
2692
|
+
//#region src/dataSources/index.ts
|
|
2693
|
+
var dataSources_default = {
|
|
2694
|
+
selectComputer,
|
|
2695
|
+
selectMobileDevice: (0, _prismatic_io_spectral.dataSource)({
|
|
2696
|
+
display: {
|
|
2697
|
+
label: "Select Mobile Device",
|
|
2698
|
+
description: "Dynamically fetch a list of mobile devices from Jamf Pro for use in a dropdown."
|
|
2699
|
+
},
|
|
2700
|
+
dataSourceType: "picklist",
|
|
2701
|
+
inputs: selectMobileDeviceInputs,
|
|
2702
|
+
perform: async (_context, { connection }) => {
|
|
2703
|
+
const { results } = await paginateResults(await createClient(connection, false), "/v2/mobile-devices", true, {});
|
|
2704
|
+
return { result: mapToSortedElements(results, "id", "name") };
|
|
2705
|
+
},
|
|
2706
|
+
examplePayload: selectMobileDeviceExamplePayload
|
|
2707
|
+
}),
|
|
2708
|
+
selectDepartment,
|
|
2709
|
+
selectCategory,
|
|
2710
|
+
selectPackage: (0, _prismatic_io_spectral.dataSource)({
|
|
2711
|
+
display: {
|
|
2712
|
+
label: "Select Package",
|
|
2713
|
+
description: "Dynamically fetch a list of packages from Jamf Pro for use in a dropdown."
|
|
2714
|
+
},
|
|
2715
|
+
dataSourceType: "picklist",
|
|
2716
|
+
inputs: selectPackageInputs,
|
|
2717
|
+
perform: async (_context, { connection }) => {
|
|
2718
|
+
const { results } = await paginateResults(await createClient(connection, false), "/v1/packages", true, {});
|
|
2719
|
+
return { result: mapToSortedElements(results, "id", "packageName") };
|
|
2720
|
+
},
|
|
2721
|
+
examplePayload: selectPackageExamplePayload
|
|
2722
|
+
}),
|
|
2723
|
+
selectScript: (0, _prismatic_io_spectral.dataSource)({
|
|
2724
|
+
display: {
|
|
2725
|
+
label: "Select Script",
|
|
2726
|
+
description: "Dynamically fetch a list of scripts from Jamf Pro for use in a dropdown."
|
|
2727
|
+
},
|
|
2728
|
+
dataSourceType: "picklist",
|
|
2729
|
+
inputs: selectScriptInputs,
|
|
2730
|
+
perform: async (_context, { connection }) => {
|
|
2731
|
+
const { results } = await paginateResults(await createClient(connection, false), "/v1/scripts", true, {});
|
|
2732
|
+
return { result: mapToSortedElements(results, "id", "name") };
|
|
2733
|
+
},
|
|
2734
|
+
examplePayload: selectScriptExamplePayload
|
|
2735
|
+
}),
|
|
2736
|
+
selectWebhook: (0, _prismatic_io_spectral.dataSource)({
|
|
2737
|
+
display: {
|
|
2738
|
+
label: "Select Webhook",
|
|
2739
|
+
description: "Dynamically fetch a list of webhooks from Jamf Pro for use in a dropdown."
|
|
2740
|
+
},
|
|
2741
|
+
dataSourceType: "picklist",
|
|
2742
|
+
inputs: selectWebhookInputs,
|
|
2743
|
+
perform: async (_context, { connection }) => {
|
|
2744
|
+
const { data } = await (await createClassicClient(connection, false)).get("/webhooks");
|
|
2745
|
+
return { result: mapToSortedElements(data.webhooks, "id", "name") };
|
|
2746
|
+
},
|
|
2747
|
+
examplePayload: selectWebhookExamplePayload
|
|
2748
|
+
})
|
|
2749
|
+
};
|
|
2750
|
+
//#endregion
|
|
2751
|
+
//#region src/triggers/pollNewComputers.ts
|
|
2752
|
+
const pollNewComputers = (0, _prismatic_io_spectral.pollingTrigger)({
|
|
2753
|
+
display: {
|
|
2754
|
+
label: "New Computers",
|
|
2755
|
+
description: "Retrieves existing and newly enrolled computers in Jamf Pro. Load history once, check for new enrollments on a schedule, or both."
|
|
2756
|
+
},
|
|
2757
|
+
inputs: pollComputersInputs,
|
|
2758
|
+
triggerResolverSupport: "valid",
|
|
2759
|
+
batchConfig: { batchSize: 50 },
|
|
2760
|
+
triggerResolver: {
|
|
2761
|
+
resolveItems: (_context, { payload }) => resolveNewComputerChanges(payload.body.data),
|
|
2762
|
+
getNextPaginationState: (_context, { payload }) => payload.paginationState ?? null
|
|
2763
|
+
},
|
|
2764
|
+
perform: async (context, payload, { connection, lookBackDate }) => {
|
|
2765
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2766
|
+
const state = context.polling.getState() ?? {};
|
|
2767
|
+
const incoming = payload.paginationState;
|
|
2768
|
+
const seed = lookBackDate || now;
|
|
2769
|
+
const result = await drainWatermark(fetchComputerPage(await createClient(connection, context.debug.enabled)), resolveStartCursor(state, incoming, seed), resolveSafeHorizon(now), context.batch?.enabled === true ? 1 : 20);
|
|
2770
|
+
context.polling.setState(nextPollingState(state, seed, result));
|
|
2771
|
+
context.logger.debug(`Polled ${result.delivered.length} computers, drained=${result.drained}`);
|
|
2772
|
+
return {
|
|
2773
|
+
payload: {
|
|
2774
|
+
...payload,
|
|
2775
|
+
paginationState: result.drained ? void 0 : result.cursor,
|
|
2776
|
+
body: { data: result.delivered }
|
|
2777
|
+
},
|
|
2778
|
+
polledNoChanges: result.drained && !incoming && result.delivered.length === 0
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
//#endregion
|
|
2783
|
+
//#region src/triggers/pollNewMobileDevices.ts
|
|
2784
|
+
const pollNewMobileDevices = (0, _prismatic_io_spectral.pollingTrigger)({
|
|
2785
|
+
display: {
|
|
2786
|
+
label: "New Mobile Devices",
|
|
2787
|
+
description: "Checks for newly enrolled mobile devices in Jamf Pro on a configured schedule."
|
|
2788
|
+
},
|
|
2789
|
+
inputs: pollMobileDevicesInputs,
|
|
2790
|
+
perform: async (context, payload, { connection }) => {
|
|
2791
|
+
const pollState = context.polling.getState();
|
|
2792
|
+
const lastMaxId = pollState.lastMaxId ?? 0;
|
|
2793
|
+
const isFirstRun = pollState.lastMaxId === void 0;
|
|
2794
|
+
context.logger.debug(`Polling for new mobile devices. Last known max ID: ${lastMaxId}`);
|
|
2795
|
+
const { results: allDevices } = await paginateResults(await createClient(connection, context.debug.enabled), "/v2/mobile-devices", true, {});
|
|
2796
|
+
const newMaxId = allDevices.reduce((max, d) => Math.max(max, _prismatic_io_spectral.util.types.toInt(d.id, 10) || 0), lastMaxId);
|
|
2797
|
+
context.polling.setState({ lastMaxId: newMaxId });
|
|
2798
|
+
if (isFirstRun) {
|
|
2799
|
+
context.logger.debug(`First run — established baseline of ${allDevices.length} devices. Max ID: ${newMaxId}`);
|
|
2800
|
+
return {
|
|
2801
|
+
payload: {
|
|
2802
|
+
...payload,
|
|
2803
|
+
body: { data: [] }
|
|
2804
|
+
},
|
|
2805
|
+
polledNoChanges: true
|
|
2806
|
+
};
|
|
2807
|
+
}
|
|
2808
|
+
const newDevices = allDevices.filter((d) => (_prismatic_io_spectral.util.types.toInt(d.id, 10) || 0) > lastMaxId);
|
|
2809
|
+
context.logger.debug(`Found ${newDevices.length} newly enrolled mobile devices`);
|
|
2810
|
+
return {
|
|
2811
|
+
payload: {
|
|
2812
|
+
...payload,
|
|
2813
|
+
body: { data: newDevices }
|
|
2814
|
+
},
|
|
2815
|
+
polledNoChanges: newDevices.length === 0
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
});
|
|
2819
|
+
//#endregion
|
|
2820
|
+
//#region src/triggers/index.ts
|
|
2821
|
+
var triggers_default = {
|
|
2822
|
+
webhook: (0, _prismatic_io_spectral.trigger)({
|
|
2823
|
+
display: {
|
|
2824
|
+
label: "Manual Webhook",
|
|
2825
|
+
description: "Receive and validate webhook requests from Jamf Pro for manually configured webhook subscriptions."
|
|
2826
|
+
},
|
|
2827
|
+
inputs: webhookInputs,
|
|
2828
|
+
perform: async (context, payload, { authHeaderName, authHeaderValue }) => {
|
|
2829
|
+
if (!context.isSimulatedTestExecution && authHeaderName && authHeaderValue) {
|
|
2830
|
+
if (_prismatic_io_spectral.util.types.lowerCaseHeaders(payload.headers)[authHeaderName.toLowerCase()] !== authHeaderValue) throw new Error("Jamf webhook header authentication failed: missing or invalid auth header.");
|
|
2831
|
+
}
|
|
2832
|
+
return { payload };
|
|
2833
|
+
},
|
|
2834
|
+
scheduleSupport: "invalid",
|
|
2835
|
+
synchronousResponseSupport: "valid",
|
|
2836
|
+
examplePayload: webhookExamplePayload
|
|
2837
|
+
}),
|
|
2838
|
+
webhookEvents: (0, _prismatic_io_spectral.trigger)({
|
|
2839
|
+
display: {
|
|
2840
|
+
label: "Webhook Events",
|
|
2841
|
+
description: "Subscribe to Jamf Pro events. On deploy, this trigger creates a webhook in Jamf Pro for each selected event (secured with a generated authentication header) and removes them when the instance is deleted. Incoming requests are validated against that header."
|
|
2842
|
+
},
|
|
2843
|
+
inputs: webhookEventsInputs,
|
|
2844
|
+
perform: async (context, payload) => {
|
|
2845
|
+
if (!context.isSimulatedTestExecution) {
|
|
2846
|
+
const state = context.crossFlowState[getStoreKey(context.flow.stableId)];
|
|
2847
|
+
const headers = _prismatic_io_spectral.util.types.lowerCaseHeaders(payload.headers);
|
|
2848
|
+
if (!state?.webhookAuthValue || headers["X-Jamf-Signature".toLowerCase()] !== state.webhookAuthValue) throw new Error("Jamf webhook header authentication failed: missing or invalid auth header.");
|
|
2849
|
+
}
|
|
2850
|
+
return Promise.resolve({ payload });
|
|
2851
|
+
},
|
|
2852
|
+
scheduleSupport: "invalid",
|
|
2853
|
+
synchronousResponseSupport: "invalid",
|
|
2854
|
+
examplePayload: webhookExamplePayload,
|
|
2855
|
+
webhookLifecycleHandlers: {
|
|
2856
|
+
create: createManagedWebhooks,
|
|
2857
|
+
delete: deleteManagedWebhooks
|
|
2858
|
+
}
|
|
2859
|
+
}),
|
|
2860
|
+
pollNewComputers,
|
|
2861
|
+
pollNewMobileDevices
|
|
2862
|
+
};
|
|
2863
|
+
//#endregion
|
|
2864
|
+
//#region src/index.ts
|
|
2865
|
+
var src_default = (0, _prismatic_io_spectral.component)({
|
|
2866
|
+
key: "jamf",
|
|
2867
|
+
public: true,
|
|
2868
|
+
documentationUrl: "https://prismatic.io/docs/components/jamf/",
|
|
2869
|
+
display: {
|
|
2870
|
+
label: "Jamf",
|
|
2871
|
+
description: "Manage Apple devices, policies, scripts, and users with Jamf Pro and Jamf School.",
|
|
2872
|
+
iconPath: "icon.png",
|
|
2873
|
+
category: "Application Connectors"
|
|
2874
|
+
},
|
|
2875
|
+
hooks: { error: _prismatic_io_spectral_http.handleErrors },
|
|
2876
|
+
actions: actions_default,
|
|
2877
|
+
connections: connections_default,
|
|
2878
|
+
triggers: triggers_default,
|
|
2879
|
+
dataSources: dataSources_default
|
|
2880
|
+
});
|
|
2881
|
+
//#endregion
|
|
2882
|
+
//#region npm-dist/.entry.ts
|
|
2883
|
+
var _entry_default = (0, _prismatic_io_spectral.callableComponent)(src_default);
|
|
2884
|
+
//#endregion
|
|
2885
|
+
module.exports = _entry_default;
|