diff --git a/components/snipe_it/actions/create-hardware/create-hardware.mjs b/components/snipe_it/actions/create-hardware/create-hardware.mjs new file mode 100644 index 0000000000000..78644a24737bb --- /dev/null +++ b/components/snipe_it/actions/create-hardware/create-hardware.mjs @@ -0,0 +1,228 @@ +import app from "../../snipe_it.app.mjs"; +import utils from "../../common/utils.mjs"; + +export default { + key: "snipe_it-create-hardware", + name: "Create Hardware Asset", + description: "Creates a new hardware asset in Snipe-IT. [See the documentation](https://snipe-it.readme.io/reference/hardware-create)", + version: "0.0.1", + type: "action", + props: { + app, + modelId: { + propDefinition: [ + app, + "modelId", + ], + }, + statusId: { + propDefinition: [ + app, + "statusId", + ], + }, + assetTag: { + propDefinition: [ + app, + "assetTag", + ], + }, + name: { + propDefinition: [ + app, + "name", + ], + }, + image: { + propDefinition: [ + app, + "image", + ], + }, + serial: { + propDefinition: [ + app, + "serial", + ], + }, + purchaseDate: { + propDefinition: [ + app, + "purchaseDate", + ], + }, + purchaseCost: { + propDefinition: [ + app, + "purchaseCost", + ], + }, + orderNumber: { + propDefinition: [ + app, + "orderNumber", + ], + }, + notes: { + propDefinition: [ + app, + "notes", + ], + }, + archived: { + propDefinition: [ + app, + "archived", + ], + }, + warrantyMonths: { + propDefinition: [ + app, + "warrantyMonths", + ], + }, + depreciate: { + propDefinition: [ + app, + "depreciate", + ], + }, + supplierId: { + propDefinition: [ + app, + "supplierId", + ], + }, + requestable: { + propDefinition: [ + app, + "requestable", + ], + }, + rtdLocationId: { + label: "RTD Location", + description: "Select the default location for this asset", + propDefinition: [ + app, + "locationId", + ], + }, + lastAuditDate: { + propDefinition: [ + app, + "lastAuditDate", + ], + }, + locationId: { + propDefinition: [ + app, + "locationId", + ], + }, + byod: { + propDefinition: [ + app, + "byod", + ], + }, + customFields: { + propDefinition: [ + app, + "customFields", + ], + }, + }, + async run({ $ }) { + const { + app, + modelId, + statusId, + assetTag, + name, + image, + serial, + purchaseDate, + purchaseCost, + orderNumber, + notes, + archived, + warrantyMonths, + depreciate, + supplierId, + requestable, + rtdLocationId, + lastAuditDate, + locationId, + byod, + customFields, + } = this; + + const parsedCustomFields = utils.parseJson(customFields); + + const response = await app.createHardware({ + $, + data: { + model_id: modelId, + status_id: statusId, + ...(name && { + name, + }), + ...(assetTag && { + asset_tag: assetTag, + }), + ...(image && { + image, + }), + ...(serial && { + serial, + }), + ...(purchaseDate && { + purchase_date: purchaseDate, + }), + ...(purchaseCost && { + purchase_cost: purchaseCost, + }), + ...(orderNumber && { + order_number: orderNumber, + }), + ...(notes && { + notes, + }), + ...(archived !== undefined && { + archived, + }), + ...(warrantyMonths && { + warranty_months: warrantyMonths, + }), + ...(depreciate !== undefined && { + depreciate, + }), + ...(supplierId && { + supplier_id: supplierId, + }), + ...(requestable !== undefined && { + requestable, + }), + ...(rtdLocationId && { + rtd_location_id: rtdLocationId, + }), + ...(lastAuditDate && { + last_audit_date: lastAuditDate, + }), + ...(locationId && { + location_id: locationId, + }), + ...(byod !== undefined && { + byod, + }), + ...(typeof(parsedCustomFields) === "object" + ? parsedCustomFields + : {} + ), + }, + }); + + $.export("$summary", `Successfully created hardware asset with ID \`${response.payload.id}\``); + return response; + }, +}; diff --git a/components/snipe_it/actions/create-user/create-user.mjs b/components/snipe_it/actions/create-user/create-user.mjs new file mode 100644 index 0000000000000..422b4155fd577 --- /dev/null +++ b/components/snipe_it/actions/create-user/create-user.mjs @@ -0,0 +1,211 @@ +import app from "../../snipe_it.app.mjs"; + +export default { + key: "snipe_it-create-user", + name: "Create User", + description: "Creates a new user in Snipe-IT with profile information required for asset or license assignments. [See the documentation](https://snipe-it.readme.io/reference/users-2)", + version: "0.0.1", + type: "action", + props: { + app, + firstName: { + propDefinition: [ + app, + "firstName", + ], + }, + username: { + propDefinition: [ + app, + "username", + ], + }, + password: { + propDefinition: [ + app, + "password", + ], + }, + passwordConfirmation: { + propDefinition: [ + app, + "passwordConfirmation", + ], + }, + lastName: { + propDefinition: [ + app, + "lastName", + ], + }, + email: { + propDefinition: [ + app, + "email", + ], + }, + activated: { + propDefinition: [ + app, + "activated", + ], + }, + phone: { + propDefinition: [ + app, + "phone", + ], + }, + jobtitle: { + propDefinition: [ + app, + "jobtitle", + ], + }, + managerId: { + propDefinition: [ + app, + "managerId", + ], + }, + employeeNum: { + propDefinition: [ + app, + "employeeNum", + ], + }, + notes: { + description: "Notes about the user", + propDefinition: [ + app, + "notes", + ], + }, + companyId: { + propDefinition: [ + app, + "companyId", + ], + }, + twoFactorEnrolled: { + propDefinition: [ + app, + "twoFactorEnrolled", + ], + }, + twoFactorOptIn: { + propDefinition: [ + app, + "twoFactorOptIn", + ], + }, + departmentId: { + propDefinition: [ + app, + "departmentId", + ], + }, + locationId: { + propDefinition: [ + app, + "locationId", + ], + }, + remote: { + propDefinition: [ + app, + "remote", + ], + }, + groups: { + propDefinition: [ + app, + "groupIds", + ], + }, + autoAssignLicenses: { + propDefinition: [ + app, + "autoAssignLicenses", + ], + }, + vip: { + propDefinition: [ + app, + "vip", + ], + }, + startDate: { + propDefinition: [ + app, + "startDate", + ], + }, + endDate: { + propDefinition: [ + app, + "endDate", + ], + }, + }, + async run({ $ }) { + const { + app, + firstName, + username, + password, + passwordConfirmation, + lastName, + email, + activated, + phone, + jobtitle, + managerId, + employeeNum, + notes, + companyId, + twoFactorEnrolled, + twoFactorOptIn, + departmentId, + locationId, + remote, + groups, + autoAssignLicenses, + vip, + startDate, + endDate, + } = this; + + const response = await app.createUser({ + $, + data: { + first_name: firstName, + username, + password, + password_confirmation: passwordConfirmation, + last_name: lastName, + email, + activated, + phone, + jobtitle, + manager_id: managerId, + employee_num: employeeNum, + notes, + company_id: companyId, + two_factor_enrolled: twoFactorEnrolled, + two_factor_optin: twoFactorOptIn, + department_id: departmentId, + location_id: locationId, + remote, + groups, + autoassign_licenses: autoAssignLicenses, + vip, + start_date: startDate, + end_date: endDate, + }, + }); + + $.export("$summary", `Successfully created user with ID \`${response.payload.id}\``); + return response; + }, +}; diff --git a/components/snipe_it/actions/get-hardware/get-hardware.mjs b/components/snipe_it/actions/get-hardware/get-hardware.mjs new file mode 100644 index 0000000000000..bff2d401ded8a --- /dev/null +++ b/components/snipe_it/actions/get-hardware/get-hardware.mjs @@ -0,0 +1,27 @@ +import app from "../../snipe_it.app.mjs"; + +export default { + key: "snipe_it-get-hardware", + name: "Get Hardware Asset", + description: "Retrieves details of a specific hardware asset by ID. [See the documentation](https://snipe-it.readme.io/reference/hardware-by-id)", + version: "0.0.1", + type: "action", + props: { + app, + hardwareId: { + propDefinition: [ + app, + "hardwareId", + ], + }, + }, + async run({ $ }) { + const response = await this.app.getHardware({ + $, + hardwareId: this.hardwareId, + }); + + $.export("$summary", `Successfully retrieved hardware asset details with ID \`${response.id}\``); + return response; + }, +}; diff --git a/components/snipe_it/actions/get-license/get-license.mjs b/components/snipe_it/actions/get-license/get-license.mjs new file mode 100644 index 0000000000000..97693f14b026b --- /dev/null +++ b/components/snipe_it/actions/get-license/get-license.mjs @@ -0,0 +1,32 @@ +import app from "../../snipe_it.app.mjs"; + +export default { + key: "snipe_it-get-license", + name: "Get License", + description: "Retrieves license details including seat count, expiration, and current usage metrics. Note: The response returns 'product_key' but uses 'serial' field for POST/PUT/PATCH requests. [See the documentation](https://snipe-it.readme.io/reference/licensesid)", + version: "0.0.1", + type: "action", + props: { + app, + licenseId: { + propDefinition: [ + app, + "licenseId", + ], + }, + }, + async run({ $ }) { + const { + app, + licenseId, + } = this; + + const response = await app.getLicense({ + $, + licenseId, + }); + + $.export("$summary", `Successfully retrieved license with ID \`${response.id}\``); + return response; + }, +}; diff --git a/components/snipe_it/actions/get-user-assets/get-user-assets.mjs b/components/snipe_it/actions/get-user-assets/get-user-assets.mjs new file mode 100644 index 0000000000000..3585ccacab10c --- /dev/null +++ b/components/snipe_it/actions/get-user-assets/get-user-assets.mjs @@ -0,0 +1,32 @@ +import app from "../../snipe_it.app.mjs"; + +export default { + key: "snipe_it-get-user-assets", + name: "Get User Assets", + description: "Retrieves all assets currently assigned to a specific user. Useful for audits and inventory reviews. [See the documentation](https://snipe-it.readme.io/reference/usersidassets)", + version: "0.0.1", + type: "action", + props: { + app, + userId: { + propDefinition: [ + app, + "userId", + ], + }, + }, + async run({ $ }) { + const { + app, + userId, + } = this; + + const response = await app.getUserAssets({ + $, + userId, + }); + + $.export("$summary", `Successfully retrieved \`${response.rows.length}\` assets for user ID \`${userId}\``); + return response; + }, +}; diff --git a/components/snipe_it/actions/update-hardware/update-hardware.mjs b/components/snipe_it/actions/update-hardware/update-hardware.mjs new file mode 100644 index 0000000000000..e4396ac2acac2 --- /dev/null +++ b/components/snipe_it/actions/update-hardware/update-hardware.mjs @@ -0,0 +1,284 @@ +import app from "../../snipe_it.app.mjs"; +import utils from "../../common/utils.mjs"; + +export default { + key: "snipe_it-update-hardware", + name: "Update Hardware Asset", + description: "Partially updates information about an existing hardware asset. [See the documentation](https://snipe-it.readme.io/reference/hardware-partial-update)", + version: "0.0.1", + type: "action", + props: { + app, + hardwareId: { + propDefinition: [ + app, + "hardwareId", + ], + description: "Select the hardware asset to update", + }, + assetTag: { + propDefinition: [ + app, + "assetTag", + ], + description: "Update the asset tag", + }, + notes: { + propDefinition: [ + app, + "notes", + ], + description: "Update notes about the asset", + }, + statusId: { + optional: true, + propDefinition: [ + app, + "statusId", + ], + description: "Update the status of the asset", + }, + modelId: { + optional: true, + propDefinition: [ + app, + "modelId", + ], + description: "Update the model of the asset", + }, + lastCheckout: { + propDefinition: [ + app, + "lastCheckout", + ], + description: "Update the last checkout date", + }, + assignedUser: { + optional: true, + propDefinition: [ + app, + "userId", + ], + label: "Assigned User", + description: "The ID of the user the asset should be checked out to", + }, + assignedLocation: { + optional: true, + propDefinition: [ + app, + "userId", + ], + label: "Assigned Location", + description: "The ID of the user the location should be checked out to", + }, + assignedAsset: { + optional: true, + propDefinition: [ + app, + "hardwareId", + ], + label: "Assigned Asset", + description: "The ID of the asset the asset should be checked out to", + }, + companyId: { + propDefinition: [ + app, + "companyId", + ], + description: "The ID of an associated company id", + }, + serial: { + propDefinition: [ + app, + "serial", + ], + description: "Serial number of the asset", + }, + orderNumber: { + propDefinition: [ + app, + "orderNumber", + ], + description: "Update the order number", + }, + warrantyMonths: { + propDefinition: [ + app, + "warrantyMonths", + ], + description: "Update the warranty period", + }, + purchaseCost: { + propDefinition: [ + app, + "purchaseCost", + ], + description: "Update the purchase cost", + }, + purchaseDate: { + propDefinition: [ + app, + "purchaseDate", + ], + description: "Update the purchase date", + }, + requestable: { + propDefinition: [ + app, + "requestable", + ], + description: "Update whether the asset can be requested", + }, + archived: { + propDefinition: [ + app, + "archived", + ], + description: "Update the archived status", + }, + rtdLocationId: { + propDefinition: [ + app, + "locationId", + ], + description: "Update the RTD location", + }, + name: { + propDefinition: [ + app, + "name", + ], + description: "Update the name of the asset", + }, + locationId: { + propDefinition: [ + app, + "locationId", + ], + description: "Update the location of the asset", + }, + byod: { + propDefinition: [ + app, + "byod", + ], + description: "Update the BYOD", + }, + customFields: { + propDefinition: [ + app, + "customFields", + ], + description: "Update custom fields using DB field names from Settings > Custom Fields", + }, + }, + async run({ $ }) { + const { + app, + hardwareId, + assetTag, + notes, + statusId, + modelId, + lastCheckout, + assignedUser, + assignedLocation, + assignedAsset, + companyId, + serial, + orderNumber, + warrantyMonths, + purchaseCost, + purchaseDate, + requestable, + archived, + rtdLocationId, + name, + locationId, + byod, + customFields, + } = this; + + const parsedCustomFields = utils.parseJson(customFields); + + const data = { + ...(assetTag && { + asset_tag: assetTag, + }), + ...(notes && { + notes, + }), + ...(statusId && { + status_id: statusId, + }), + ...(modelId && { + model_id: modelId, + }), + ...(lastCheckout && { + last_checkout: lastCheckout, + }), + ...(assignedUser && { + assigned_user_id: assignedUser, + }), + ...(assignedLocation && { + assigned_location_id: assignedLocation, + }), + ...(assignedAsset && { + assigned_asset_id: assignedAsset, + }), + ...(companyId && { + company_id: companyId, + }), + ...(serial && { + serial, + }), + ...(orderNumber && { + order_number: orderNumber, + }), + ...(warrantyMonths && { + warranty_months: warrantyMonths, + }), + ...(purchaseCost && { + purchase_cost: purchaseCost, + }), + ...(purchaseDate && { + purchase_date: purchaseDate, + }), + ...(requestable && { + requestable, + }), + ...(archived && { + archived, + }), + ...(rtdLocationId && { + rtd_location_id: rtdLocationId, + }), + ...(name && { + name, + }), + ...(locationId && { + location_id: locationId, + }), + ...(byod && { + byod, + }), + ...(typeof(parsedCustomFields) === "object" + ? parsedCustomFields + : {} + ), + }; + + if (Object.keys(data).length === 0) { + throw new Error("At least one field must be provided to update"); + } + + const response = await app.updateHardware({ + $, + hardwareId, + data, + }); + + $.export("$summary", `Successfully updated hardware asset with ID \`${response.payload.id}\``); + return response; + }, +}; diff --git a/components/snipe_it/common/utils.mjs b/components/snipe_it/common/utils.mjs new file mode 100644 index 0000000000000..2adf04343104f --- /dev/null +++ b/components/snipe_it/common/utils.mjs @@ -0,0 +1,44 @@ +const parseJson = (input, maxDepth = 100) => { + const seen = new WeakSet(); + const parse = (value) => { + if (maxDepth <= 0) { + return value; + } + if (typeof(value) === "string") { + // Only parse if the string looks like a JSON object or array + const trimmed = value.trim(); + if ( + (trimmed.startsWith("{") && trimmed.endsWith("}")) || + (trimmed.startsWith("[") && trimmed.endsWith("]")) + ) { + try { + return parseJson(JSON.parse(value), maxDepth - 1); + } catch (e) { + return value; + } + } + return value; + } else if (typeof(value) === "object" && value !== null && !Array.isArray(value)) { + if (seen.has(value)) { + return value; + } + seen.add(value); + return Object.entries(value) + .reduce((acc, [ + key, + val, + ]) => Object.assign(acc, { + [key]: parse(val), + }), {}); + } else if (Array.isArray(value)) { + return value.map((item) => parse(item)); + } + return value; + }; + + return parse(input); +}; + +export default { + parseJson, +}; diff --git a/components/snipe_it/package.json b/components/snipe_it/package.json index cea32e5940bdb..fe79bf48989a2 100644 --- a/components/snipe_it/package.json +++ b/components/snipe_it/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/snipe_it", - "version": "0.0.1", + "version": "0.1.0", "description": "Pipedream Snipe-IT Components", "main": "snipe_it.app.mjs", "keywords": [ @@ -11,5 +11,8 @@ "author": "Pipedream (https://pipedream.com/)", "publishConfig": { "access": "public" + }, + "dependencies": { + "@pipedream/platform": "^3.1.0" } -} \ No newline at end of file +} diff --git a/components/snipe_it/snipe_it.app.mjs b/components/snipe_it/snipe_it.app.mjs index f0411fdaba9e1..a988e3e0059ed 100644 --- a/components/snipe_it/snipe_it.app.mjs +++ b/components/snipe_it/snipe_it.app.mjs @@ -1,11 +1,572 @@ +import { axios } from "@pipedream/platform"; + export default { type: "app", app: "snipe_it", - propDefinitions: {}, + propDefinitions: { + modelId: { + type: "integer", + label: "Model", + description: "Select the model for this asset", + async options({ page }) { + const { rows } = await this.listModels({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + statusId: { + type: "integer", + label: "Status", + description: "Select the status label for this asset", + async options({ page }) { + const { rows } = await this.listStatusLabels({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + assetTag: { + type: "string", + label: "Asset Tag", + description: "The asset tag for the asset", + optional: true, + }, + name: { + type: "string", + label: "Asset Name", + description: "The name of the asset", + optional: true, + }, + image: { + type: "string", + label: "Image", + description: "Base64 encoded image. Eg. `data:@[mime];base64,[base64encodeddata]`.", + optional: true, + }, + serial: { + type: "string", + label: "Serial Number", + description: "The serial number of the asset", + optional: true, + }, + purchaseDate: { + type: "string", + label: "Purchase Date", + description: "The purchase date of the asset (YYYY-MM-DD format)", + optional: true, + }, + purchaseCost: { + type: "string", + label: "Purchase Cost", + description: "The purchase cost of the asset", + optional: true, + }, + orderNumber: { + type: "string", + label: "Order Number", + description: "The order number of the asset", + optional: true, + }, + notes: { + type: "string", + label: "Notes", + description: "Notes about the asset", + optional: true, + }, + archived: { + type: "boolean", + label: "Archived", + description: "Whether the asset is archived", + optional: true, + }, + warrantyMonths: { + type: "integer", + label: "Warranty Months", + description: "The warranty period in months", + optional: true, + }, + depreciate: { + type: "boolean", + label: "Depreciate", + description: "Whether the asset is depreciated", + optional: true, + }, + supplierId: { + type: "integer", + label: "Supplier", + description: "Select the supplier for this asset", + optional: true, + async options({ page }) { + const { rows } = await this.listSuppliers({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + requestable: { + type: "boolean", + label: "Requestable", + description: "Whether this asset can be requested by users", + optional: true, + }, + lastAuditDate: { + type: "string", + label: "Last Audit Date", + description: "The date of the last audit for this asset (YYYY-MM-DD format)", + optional: true, + }, + locationId: { + type: "integer", + label: "Location", + description: "Select the location where this asset is located", + optional: true, + async options({ page }) { + const { rows } = await this.listLocations({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + byod: { + type: "boolean", + label: "BYOD", + description: "Whether this asset is a BYOD device.", + optional: true, + }, + customFields: { + type: "object", + label: "Custom Fields", + description: "Custom fields for the asset", + optional: true, + }, + hardwareId: { + type: "integer", + label: "Hardware Asset", + description: "Select the hardware asset to retrieve details for", + async options({ page }) { + const { rows } = await this.listHardware({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name, asset_tag: assetTag, + }) => ({ + label: name + ? `${name} (${assetTag || `ID: ${value}`})` + : assetTag || `Asset ID: ${value}`, + value, + })) || []; + }, + }, + userId: { + type: "integer", + label: "User", + description: "Select the user to retrieve assigned assets for", + async options({ page }) { + const { rows } = await this.listUsers({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name, username, email, + }) => ({ + label: name + ? `${name} (${email || username})` + : email || username || `User ID: ${value}`, + value, + })) || []; + }, + }, + firstName: { + type: "string", + label: "First Name", + description: "The first name of the user", + }, + lastName: { + type: "string", + label: "Last Name", + description: "The last name of the user", + optional: true, + }, + username: { + type: "string", + label: "Username", + description: "The username for the user (required for login)", + }, + password: { + type: "string", + label: "Password", + description: "The password for the user account", + secret: true, + }, + passwordConfirmation: { + type: "string", + label: "Password Confirmation", + description: "The password confirmation for the user account", + secret: true, + }, + email: { + type: "string", + label: "Email", + description: "The email address of the user", + optional: true, + }, + activated: { + type: "boolean", + label: "Activated", + description: "Whether the user account is activated", + optional: true, + }, + phone: { + type: "string", + label: "Phone", + description: "The phone number of the user", + optional: true, + }, + jobtitle: { + type: "string", + label: "Job Title", + description: "The job title of the user", + optional: true, + }, + managerId: { + type: "integer", + label: "Manager", + description: "Select the manager for this user", + optional: true, + async options({ page }) { + const { rows } = await this.listUsers({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name, username, email, + }) => ({ + label: name + ? `${name} (${email || username})` + : email || username || `User ID: ${value}`, + value, + })) || []; + }, + }, + employeeNum: { + type: "string", + label: "Employee Number", + description: "The employee number of the user", + optional: true, + }, + companyId: { + type: "integer", + label: "Company", + description: "Select the company for this user", + optional: true, + async options({ page }) { + const { rows } = await this.listCompanies({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + twoFactorEnrolled: { + type: "boolean", + label: "Two Factor Enrolled", + description: "Whether the user is enrolled in two-factor authentication", + optional: true, + }, + twoFactorOptIn: { + type: "boolean", + label: "Two Factor Opt In", + description: "Whether the user has opted in to two-factor authentication", + optional: true, + }, + departmentId: { + type: "integer", + label: "Department", + description: "Select the department for this user", + optional: true, + async options({ page }) { + const { rows } = await this.listDepartments({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + remote: { + type: "boolean", + label: "Remote", + description: "Whether or not the user is a remote worker", + optional: true, + }, + groupIds: { + type: "string[]", + label: "Groups", + description: "Select the groups for this user", + optional: true, + async options({ page }) { + const { rows } = await this.listGroups({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name: label, + }) => ({ + label, + value, + })) || []; + }, + }, + autoAssignLicenses: { + type: "boolean", + label: "Auto Assign Licenses", + description: "Whether to automatically assign licenses to the user", + optional: true, + }, + vip: { + type: "boolean", + label: "VIP", + description: "Whether this user is a VIP", + optional: true, + }, + startDate: { + type: "string", + label: "Start Date", + description: "The user's start date (YYYY-MM-DD format)", + optional: true, + }, + endDate: { + type: "string", + label: "End Date", + description: "The user's end date (YYYY-MM-DD format)", + optional: true, + }, + licenseId: { + type: "integer", + label: "License", + description: "Select the license to retrieve details for", + async options({ page }) { + const { rows } = await this.listLicenses({ + params: { + limit: 50, + offset: page * 50, + }, + }); + return rows?.map(({ + id: value, name, product_key: productKey, manufacturer, + }) => ({ + label: name + ? `${name} ${productKey + ? `(${productKey})` + : ""} - ${manufacturer?.name || "No manufacturer"}` + : productKey || `License ID: ${value}`, + value, + })) || []; + }, + }, + lastCheckout: { + type: "string", + label: "Last Checkout", + description: "The last checkout date of the asset (YYYY-MM-DD format)", + optional: true, + }, + }, methods: { - // this.$auth contains connected account data - authKeys() { - console.log(Object.keys(this.$auth)); + getUrl(path) { + return `${this.$auth.api_url}/api/v1${path}`; + }, + getHeaders() { + return { + "Authorization": `Bearer ${this.$auth.api_key}`, + "Accept": "application/json", + "Content-Type": "application/json", + }; + }, + async makeRequest({ + $ = this, path, ...args + } = {}) { + const response = await axios($, { + url: this.getUrl(path), + headers: this.getHeaders(), + ...args, + }); + + if (response.status === "error") { + throw JSON.stringify(response, null, 2); + } + + return response; + }, + post(args = {}) { + return this.makeRequest({ + ...args, + method: "POST", + }); + }, + patch(args = {}) { + return this.makeRequest({ + ...args, + method: "PATCH", + }); + }, + createHardware(args = {}) { + return this.post({ + path: "/hardware", + ...args, + }); + }, + getHardware({ + hardwareId, ...args + } = {}) { + return this.makeRequest({ + path: `/hardware/${hardwareId}`, + ...args, + }); + }, + updateHardware({ + hardwareId, ...args + } = {}) { + return this.patch({ + path: `/hardware/${hardwareId}`, + ...args, + }); + }, + listHardware(args = {}) { + return this.makeRequest({ + path: "/hardware", + ...args, + }); + }, + listModels(args = {}) { + return this.makeRequest({ + path: "/models", + ...args, + }); + }, + listStatusLabels(args = {}) { + return this.makeRequest({ + path: "/statuslabels", + ...args, + }); + }, + listSuppliers(args = {}) { + return this.makeRequest({ + path: "/suppliers", + ...args, + }); + }, + listLocations(args = {}) { + return this.makeRequest({ + path: "/locations", + ...args, + }); + }, + listUsers(args = {}) { + return this.makeRequest({ + path: "/users", + ...args, + }); + }, + getUserAssets({ + userId, ...args + } = {}) { + return this.makeRequest({ + path: `/users/${userId}/assets`, + ...args, + }); + }, + createUser(args = {}) { + return this.post({ + path: "/users", + ...args, + }); + }, + listDepartments(args = {}) { + return this.makeRequest({ + path: "/departments", + ...args, + }); + }, + listCompanies(args = {}) { + return this.makeRequest({ + path: "/companies", + ...args, + }); + }, + listGroups(args = {}) { + return this.makeRequest({ + path: "/groups", + ...args, + }); + }, + listLicenses(args = {}) { + return this.makeRequest({ + path: "/licenses", + ...args, + }); + }, + getLicense({ + licenseId, ...args + } = {}) { + return this.makeRequest({ + path: `/licenses/${licenseId}`, + ...args, + }); }, }, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6496e14c5a618..ab6bd56d90220 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13200,7 +13200,11 @@ importers: specifier: ^3.0.0 version: 3.0.3 - components/snipe_it: {} + components/snipe_it: + dependencies: + '@pipedream/platform': + specifier: ^3.1.0 + version: 3.1.0 components/snov: dependencies: @@ -23371,12 +23375,6 @@ packages: axios@1.7.7: resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} - axios@1.8.4: - resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==} - - axios@1.9.0: - resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} - axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} @@ -36818,7 +36816,7 @@ snapshots: '@bandwidth/messaging@4.1.7': dependencies: '@apimatic/schema': 0.6.0 - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) detect-node: 2.1.0 form-data: 3.0.2 json-bigint: 1.0.0 @@ -38488,7 +38486,7 @@ snapshots: dependencies: '@types/body-parser': 1.19.5 '@types/node': 18.19.64 - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) body-parser: 1.20.3 file-type: 16.5.4 form-data: 4.0.3 @@ -38510,7 +38508,7 @@ snapshots: '@lob/lob-typescript-sdk@1.3.5': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) tslib: 2.8.1 transitivePeerDependencies: - debug @@ -39582,7 +39580,7 @@ snapshots: '@pipedream/linkedin@0.1.1': dependencies: '@pipedream/platform': 1.6.6 - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) form-data: 4.0.3 transitivePeerDependencies: - debug @@ -39638,7 +39636,7 @@ snapshots: '@pipedream/platform@1.6.0': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39647,7 +39645,7 @@ snapshots: '@pipedream/platform@1.6.2': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39656,7 +39654,7 @@ snapshots: '@pipedream/platform@1.6.4': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39665,7 +39663,7 @@ snapshots: '@pipedream/platform@1.6.5': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39674,7 +39672,7 @@ snapshots: '@pipedream/platform@1.6.6': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39683,7 +39681,7 @@ snapshots: '@pipedream/platform@2.0.0': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39692,7 +39690,7 @@ snapshots: '@pipedream/platform@3.0.1': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.9 io-ts: 2.2.21(fp-ts@2.16.9) querystring: 0.2.1 @@ -39701,7 +39699,7 @@ snapshots: '@pipedream/platform@3.0.3': dependencies: - axios: 1.9.0 + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.10 io-ts: 2.2.22(fp-ts@2.16.10) querystring: 0.2.1 @@ -39710,7 +39708,7 @@ snapshots: '@pipedream/platform@3.1.0': dependencies: - axios: 1.10.0 + axios: 1.10.0(debug@3.2.7) fp-ts: 2.16.10 io-ts: 2.2.22(fp-ts@2.16.10) mime-types: 3.0.1 @@ -41118,7 +41116,7 @@ snapshots: '@shortcut/client@2.2.0': dependencies: - axios: 1.10.0 + axios: 1.10.0(debug@3.2.7) transitivePeerDependencies: - debug @@ -41190,7 +41188,7 @@ snapshots: '@slack/types': 2.14.0 '@types/node': 20.17.6 '@types/retry': 0.12.0 - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) eventemitter3: 5.0.1 form-data: 4.0.3 is-electron: 2.2.2 @@ -42130,7 +42128,7 @@ snapshots: '@types/axios@0.14.4': dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) transitivePeerDependencies: - debug @@ -43395,7 +43393,7 @@ snapshots: dependencies: '@aws-sdk/util-utf8-browser': 3.259.0 '@httptoolkit/websocket-stream': 6.0.1 - axios: 1.10.0 + axios: 1.10.0(debug@3.2.7) buffer: 6.0.3 crypto-js: 4.2.0 mqtt: 4.3.8 @@ -43453,7 +43451,7 @@ snapshots: transitivePeerDependencies: - debug - axios@1.10.0: + axios@1.10.0(debug@3.2.7): dependencies: follow-redirects: 1.15.9(debug@3.2.7) form-data: 4.0.3 @@ -43501,22 +43499,6 @@ snapshots: transitivePeerDependencies: - debug - axios@1.8.4(debug@3.2.7): - dependencies: - follow-redirects: 1.15.9(debug@3.2.7) - form-data: 4.0.3 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - - axios@1.9.0: - dependencies: - follow-redirects: 1.15.9(debug@3.2.7) - form-data: 4.0.3 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - axobject-query@4.1.0: {} b4a@1.6.7: {} @@ -44342,7 +44324,7 @@ snapshots: columns-sdk@0.0.6: dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) columns-graph-model: 1.1.4 nebula-js-lib: 0.3.2 pako: 2.1.0 @@ -48086,7 +48068,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.1(supports-color@10.0.0) + debug: 4.3.7(supports-color@9.4.0) transitivePeerDependencies: - supports-color @@ -49604,7 +49586,7 @@ snapshots: klaviyo-api@18.0.0: dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) form-data: 4.0.3 transitivePeerDependencies: - debug @@ -49753,7 +49735,7 @@ snapshots: linkup-sdk@1.0.3: dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) zod: 3.24.1 zod-to-json-schema: 3.24.1(zod@3.24.1) transitivePeerDependencies: @@ -52449,7 +52431,7 @@ snapshots: pipedrive@24.1.1: dependencies: - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) qs: 6.14.0 transitivePeerDependencies: - debug @@ -52474,7 +52456,7 @@ snapshots: plaid@33.0.0: dependencies: - axios: 1.9.0 + axios: 1.10.0(debug@3.2.7) transitivePeerDependencies: - debug @@ -54535,7 +54517,7 @@ snapshots: agent-base: 6.0.2 asn1.js-rfc2560: 5.0.1(asn1.js@5.4.1) asn1.js-rfc5280: 3.0.0 - axios: 1.8.4(debug@3.2.7) + axios: 1.10.0(debug@3.2.7) big-integer: 1.6.52 bignumber.js: 2.4.0 binascii: 0.0.2 @@ -56294,7 +56276,7 @@ snapshots: utopianlabs@0.1.11: dependencies: - axios: 1.9.0 + axios: 1.10.0(debug@3.2.7) zod: 3.24.4 transitivePeerDependencies: - debug