import { ITGlueClient } from '../client'; import { QueryUtilOptions, QueryParams, RequestBody, BaseListResponse, BaseItemResponse, TagResource } from '../types'; /** * Tags resource module for IT Glue API * * Provides methods to interact with the /tags endpoint. * Tags are labels that can be applied to various resources throughout IT Glue * to provide categorization, organization, and improved searchability. They enable * flexible resource classification beyond standard categories and help create * custom organizational structures for better resource management. * * Tags are essential for: * - Resource categorization and organization * - Enhanced search and filtering capabilities * - Custom classification systems * - Bulk resource management operations * - Reporting and analytics grouping * - Cross-resource relationship identification * * Tags can be applied to: * - Configurations (servers, workstations, network devices) * - Assets (hardware, software, licenses) * - Contacts (people, vendors, clients) * - Organizations (clients, departments, locations) * - Documents (policies, procedures, manuals) * - Passwords and flexible assets * - Locations and sites * * Common tag categories include: * - Environment tags (production, staging, development) * - Priority tags (critical, high, medium, low) * - Department tags (IT, HR, Finance, Sales) * - Location tags (office, datacenter, remote) * - Status tags (active, inactive, deprecated) * - Project tags (migration, upgrade, maintenance) * * ## Related Resources * Tags can be applied to and are commonly used with: * - {@link Organizations} - Categorize organizations by type, status, or department * - {@link Contacts} - Label contacts by role, department, or responsibility * - {@link Configurations} - Tag IT assets by environment, criticality, or function * - {@link Documents} - Classify documentation by type, audience, or topic * - {@link Passwords} - Organize credentials by system type or access level * - {@link FlexibleAssets} - Categorize custom assets and data * - {@link Locations} - Tag sites by type, region, or function * - {@link Attachments} - Classify files and media by content type * - {@link RelatedItems} - Create tagged relationships between resources * * @see {@link Organizations#list} for retrieving organizations with specific tags * @see {@link Configurations#list} for retrieving configurations with specific tags * @see {@link Documents#list} for retrieving documents with specific tags * @see {@link Contacts#list} for retrieving contacts with specific tags * * @example * import { ITGlueClient } from '../client'; * import { Tags } from './resources/tags'; * * const client = new ITGlueClient({ apiKey: 'your-api-key' }); * const tags = new Tags(client); * * // List tags * const list = await tags.list(); * * // Get a single tag * const tag = await tags.get('123'); * * // Create a tag * const created = await tags.create({ * data: { type: 'tags', attributes: { name: 'New Tag' } }, * }); * * // Update a tag * const updated = await tags.update('123', { * data: { type: 'tags', attributes: { name: 'Updated Tag' } }, * }); * * // Delete a tag * await tags.delete('123'); * * @category System & Audit */ export declare class Tags { private client; private basePath; private paginationUtil; /** * Create a Tags resource instance * @param {ITGlueClient} client - ITGlueClient instance */ constructor(client: ITGlueClient); /** * List all tags * * Retrieves a list of all tags in your IT Glue organization. * This includes tag names, usage counts, and associated resource types. * Use filtering options to find specific tags by name or usage patterns. * Tags are returned with information about how frequently they're used * across different resource types. * * @param {QueryUtilOptions} [options] - Optional query parameters (filter, sort, page, etc.) * @param {boolean} [allPages=false] - If true, fetches all pages automatically * @returns {Promise>} List of tags and pagination metadata * @example * // Basic usage - get first page of tags * const results = await client.tags.list(); * console.log(`Found ${results.data.length} tags`); * console.log('Total pages:', results.meta.pagination.total_pages); * * @example * // Advanced usage with pagination and sorting * const results = await client.tags.list({ * page: { number: 2, size: 50 }, * sort: '-usage_count', // Sort by most used tags * include: ['tagged_resources'] // Include related data * }); * * @example * // Filtering tags by name pattern * const productionTags = await client.tags.list({ * filter: { * name: 'production' * }, * sort: 'name' * }); * * console.log('Production-related tags:'); * productionTags.data.forEach(tag => { * console.log(`- ${tag.attributes.name}: ${tag.attributes.usage_count || 0} uses`); * }); * * @example * // Get all tags for comprehensive analysis * const allTags = await client.tags.list({}, true); // allPages = true * * // Analyze tag usage patterns * const tagAnalysis = { * totalTags: allTags.data.length, * mostUsed: allTags.data.sort((a, b) => (b.attributes.usage_count || 0) - (a.attributes.usage_count || 0)).slice(0, 10), * unused: allTags.data.filter(tag => (tag.attributes.usage_count || 0) === 0), * categories: {} * }; * * // Group tags by category (based on naming patterns) * allTags.data.forEach(tag => { * const name = tag.attributes.name.toLowerCase(); * let category = 'Other'; * * if (name.includes('prod') || name.includes('production')) category = 'Environment'; * else if (name.includes('critical') || name.includes('high')) category = 'Priority'; * else if (name.includes('it') || name.includes('hr') || name.includes('finance')) category = 'Department'; * else if (name.includes('server') || name.includes('network')) category = 'Infrastructure'; * * if (!tagAnalysis.categories[category]) tagAnalysis.categories[category] = []; * tagAnalysis.categories[category].push(tag); * }); * * console.log('Tag analysis:', tagAnalysis); * * @example * // Manual pagination for large tag datasets * async function getAllTags() { * let page = 1; * let allResults = []; * let hasMore = true; * * while (hasMore) { * const response = await client.tags.list({ * page: { number: page, size: 100 }, * sort: 'name' * }); * * allResults = [...allResults, ...response.data]; * hasMore = response.meta.pagination.total_pages > page; * page++; * } * * return allResults; * } * * @example * // Tag usage analytics and cleanup recommendations * const tagUsageAnalysis = await client.tags.list({ * sort: '-usage_count', * include: ['tagged_resources'] * }); * * // Identify cleanup opportunities * const cleanupCandidates = tagUsageAnalysis.data.filter(tag => { * const usageCount = tag.attributes.usage_count || 0; * return usageCount === 0 || usageCount < 3; // Tags with very low usage * }); * * console.log(`Found ${cleanupCandidates.length} tags that might need cleanup:`); * cleanupCandidates.forEach(tag => { * console.log(`- "${tag.attributes.name}": ${tag.attributes.usage_count || 0} uses`); * }); * * @example * // Error handling for list operations * try { * const results = await client.tags.list({ * filter: { invalid_field: 'value' } * }); * } catch (error) { * if (error.response?.status === 400) { * console.log('Invalid filter parameters:', error.response.data.errors); * } else if (error.response?.status === 401) { * console.log('Authentication failed - check your API key'); * } else if (error.response?.status === 403) { * console.log('Access denied - insufficient permissions to view tags'); * } else { * console.log('Request failed:', error.message); * } * } */ list(options?: QueryUtilOptions, allPages?: boolean): Promise>; /** * Get a single tag by ID * * Retrieves detailed information about a specific tag, including * its usage statistics, associated resources, and metadata. * This is useful for understanding tag usage patterns and managing * tag-based organization strategies. * * @param {string} id - Tag ID (required) * @param {QueryParams} [params] - Optional query parameters * @returns {Promise>} Tag resource * @throws {Error} When tag not found (404) or access denied (403) * @example * // Basic usage - get tag by ID * const tag = await client.tags.get('123'); * console.log('Tag name:', tag.data.attributes.name); * console.log('Usage count:', tag.data.attributes.usage_count); * console.log('Description:', tag.data.attributes.description); * * @example * // Get tag with usage statistics and associated resources * const tagWithDetails = await client.tags.get('123', { * include: ['tagged_resources', 'usage_statistics'] * }); * * // Access included data * const included = tagWithDetails.included || []; * const taggedResources = included.filter(item => item.type !== 'usage_statistics'); * const usageStats = included.find(item => item.type === 'usage_statistics'); * * console.log(`Tag: ${tagWithDetails.data.attributes.name}`); * console.log(`Total usage: ${tagWithDetails.data.attributes.usage_count || 0}`); * console.log(`Tagged resources: ${taggedResources.length}`); * * // Group tagged resources by type * const resourcesByType = {}; * taggedResources.forEach(resource => { * const type = resource.type; * if (!resourcesByType[type]) resourcesByType[type] = []; * resourcesByType[type].push(resource); * }); * * console.log('Resources by type:', resourcesByType); * * @example * // Detailed tag analysis for management decisions * async function analyzeTag(id) { * try { * const tag = await client.tags.get(id, { * include: ['tagged_resources'] * }); * * const data = tag.data.attributes; * const included = tag.included || []; * * const analysis = { * tagId: id, * name: data.name, * description: data.description, * usageCount: data.usage_count || 0, * createdAt: data.created_at, * lastUsed: data.updated_at, * resourceTypes: {}, * recommendations: [] * }; * * // Analyze resource distribution * included.forEach(resource => { * const type = resource.type; * if (!analysis.resourceTypes[type]) { * analysis.resourceTypes[type] = 0; * } * analysis.resourceTypes[type]++; * }); * * // Generate recommendations * if (analysis.usageCount === 0) { * analysis.recommendations.push('Consider removing unused tag'); * } else if (analysis.usageCount < 3) { * analysis.recommendations.push('Low usage - consider consolidating with similar tags'); * } else if (analysis.usageCount > 100) { * analysis.recommendations.push('High usage - consider creating sub-tags for better organization'); * } * * return analysis; * } catch (error) { * console.error('Failed to analyze tag:', error.message); * return null; * } * } * * @example * // Error handling for get operations * try { * const tag = await client.tags.get('invalid-id'); * } catch (error) { * if (error.response?.status === 404) { * console.log('Tag not found'); * } else if (error.response?.status === 403) { * console.log('Access denied - insufficient permissions to view tag'); * } else { * console.log('Error retrieving tag:', error.message); * } * } * * @example * // Safe get with existence check * async function safeGetTag(id) { * try { * const tag = await client.tags.get(id); * return tag.data; * } catch (error) { * if (error.response?.status === 404) { * return null; // Tag doesn't exist * } * throw error; // Re-throw other errors * } * } * @see * {@link Organizations#get} - Get specific organization details * {@link Organizations#list} - List organizations related to tags * {@link Configurations#get} - Get specific configuration details * {@link Configurations#list} - List configurations related to tags * {@link FlexibleAssets#get} - Get specific flexibleasset details */ get(id: string, params?: QueryParams): Promise>; /** * Create a new tag * * Creates a new tag that can be applied to various resources throughout * IT Glue. Tags should follow consistent naming conventions to maintain * organizational effectiveness. Consider creating tag hierarchies or * categories for better resource management. * * @param {RequestBody} data - Tag data (must be formatted according to JSON:API spec) * @returns {Promise>} Created tag resource * @throws {Error} When validation fails (422) or access denied (403) * @example * // Create a basic tag * await tags.create({ * data: { * type: 'tags', * attributes: { * name: 'Production', * description: 'Production environment resources' * } * } * }); * @example * // Create a department-specific tag * await tags.create({ * data: { * type: 'tags', * attributes: { * name: 'IT-Critical', * description: 'Critical IT infrastructure components', * color: '#FF0000' * } * } * }); * @example * // Error handling for tag creation * try { * const created = await tags.create(tagData); * } catch (error) { * if (error.response?.status === 422) { * console.log('Validation failed:', error.response.data.errors); * // Common issues: duplicate name, invalid characters * } else if (error.response?.status === 403) { * console.log('Insufficient permissions to create tag'); * } * } * @see * {@link Organizations#create} - Create new organization * {@link Organizations#list} - List organizations related to tags * {@link Configurations#create} - Create new configuration * {@link Configurations#list} - List configurations related to tags * {@link FlexibleAssets#create} - Create new flexibleasset */ create(data: RequestBody): Promise>; /** * Update a tag by ID * * Updates an existing tag's properties such as name, description, or color. * When updating tag names, be aware that this affects all resources currently * using this tag. Consider the impact on existing tagging strategies and * resource organization before making changes. * * @param {string} id - Tag ID (required) * @param {RequestBody} data - Updated tag data (must be formatted according to JSON:API spec) * @returns {Promise>} Updated tag resource * @throws {Error} When tag not found (404), access denied (403), or validation fails (422) * @example * // Update tag name and description * await tags.update('123', { * data: { * type: 'tags', * attributes: { * name: 'Production-Critical', * description: 'Critical production environment resources' * } * } * }); * @example * // Update tag color for visual organization * await tags.update('123', { * data: { * type: 'tags', * attributes: { * color: '#00FF00', * description: 'Updated color for better visual identification' * } * } * }); * @example * // Error handling for tag updates * try { * const updated = await tags.update('123', updateData); * } catch (error) { * if (error.response?.status === 404) { * console.log('Tag not found'); * } else if (error.response?.status === 403) { * console.log('Insufficient permissions to update tag'); * } else if (error.response?.status === 422) { * console.log('Validation failed:', error.response.data.errors); * // Common issues: duplicate name, invalid color format * } * } * @see * {@link Organizations#update} - Update organization * {@link Organizations#get} - Get specific organization details * {@link Configurations#update} - Update configuration * {@link Configurations#get} - Get specific configuration details * {@link FlexibleAssets#update} - Update flexibleasset */ update(id: string, data: RequestBody): Promise>; /** * Delete a tag by ID * * Permanently removes a tag from the system. This action will remove * the tag from all resources that currently use it. Before deleting, * consider the impact on resource organization and search capabilities. * It's recommended to review tag usage before deletion. * * @param {string} id - Tag ID (required) * @returns {Promise} * @throws {Error} When tag not found (404), access denied (403), or tag has dependencies (409) * @example * // Delete a tag * await tags.delete('123'); * @example * // Error handling for tag deletion * try { * await tags.delete('123'); * } catch (error) { * if (error.response?.status === 404) { * console.log('Tag not found'); * } else if (error.response?.status === 403) { * console.log('Insufficient permissions to delete tag'); * } else if (error.response?.status === 409) { * console.log('Cannot delete tag with active usage'); * } * } * @example * // Safe tag deletion with usage check * const tag = await tags.get('123', { include: ['usage_statistics'] }); * if (tag.data.attributes.usage_count === 0) { * await tags.delete('123'); * } else { * console.log(`Tag is used by ${tag.data.attributes.usage_count} resources`); * // Consider bulk tag replacement before deletion * } * @see * {@link Organizations#list} - List organizations related to tags * {@link Organizations#get} - Get specific organization details * {@link Configurations#list} - List configurations related to tags * {@link Configurations#get} - Get specific configuration details * {@link FlexibleAssets#list} - List flexibleassets related to tags */ delete(id: string): Promise; }