Readonly issuesIssue operations entry point.
Provides high-level helpers such as IssueOperations.create
which back the public API jml.issues.create(...). All bulk batching,
manifest handling, and hierarchy routing flows live behind this property.
Get field schema for a specific project and issue type
Returns all available fields with their types, whether they're required, and allowed values (for option/multi-option fields).
JIRA project key (e.g., "ENG")
Issue type name (e.g., "Bug", "Task")
Promise resolving to the project schema
if the project or issue type doesn't exist
const schema = await jml.getFieldSchema('ENG', 'Bug');
console.log(Object.keys(schema.fields)); // ["summary", "priority", "customfield_10024", ...]
Get issue type hierarchy configuration
Returns the JPO (JIRA Portfolio) hierarchy structure if available, showing which issue types can be parents of other issue types. Returns null if JPO is not installed (use standard parent fields instead).
Note: Hierarchy is global across all projects in the JIRA instance.
Optional options: { Optional settings (refresh: force cache refresh)
Optional refresh?: booleanPromise resolving to array of hierarchy levels or null if JPO not installed
const hierarchy = await jml.getHierarchy();
if (hierarchy) {
// JPO installed - hierarchy is an array of levels
console.log(hierarchy); // [{ id: 0, title: "Subtask", issueTypeIds: [...] }, ...]
// Find issue types at each level
const epicLevel = hierarchy.find(l => l.title === 'Epic');
console.log(`Epic issue type IDs: ${epicLevel.issueTypeIds}`);
} else {
// Standard JIRA - use built-in parent field
console.log('No JPO hierarchy - use Parent/Epic Link fields');
} * ```
Get available issue types for a project
Returns all issue types that can be created in the specified project, with their IDs and names. Useful for building UIs or validating parent-child relationships with the hierarchy structure.
Delegates to SchemaDiscovery which already fetches this data.
JIRA project key (e.g., "ENG")
Promise resolving to array of issue type metadata
if the project doesn't exist
const issueTypes = await jml.getIssueTypes('ENG');
console.log(issueTypes);
// [
// { id: "10000", name: "Epic" },
// { id: "10001", name: "Story" },
// { id: "10002", name: "Bug" },
// { id: "10003", name: "Task" },
// { id: "10004", name: "Sub-task" }
// ]
// Combine with hierarchy to validate parent-child relationships
const hierarchy = await jml.getHierarchy();
const storyType = issueTypes.find(t => t.name === 'Story');
const epicLevel = hierarchy?.find(l => l.issueTypeIds.includes(storyType.id));
Discover the parent field for a specific project and issue type
Returns information about the parent field used for linking issues in a hierarchy. The library uses this to determine which field name users can use for parent references (e.g., "Parent Link", "Epic Link").
Detection priority:
Results are cached for 1 hour to minimize API calls.
JIRA project key (e.g., "ENG")
Issue type name (e.g., "Story", "Epic")
Promise resolving to parent field info or null if not found
// Discover parent field for Stories
const parentField = await jml.getParentField('ENG', 'Story');
if (parentField) {
console.log(`Parent field: ${parentField.name} (${parentField.key})`);
// "Parent field: Parent Link (customfield_10014)"
// Now you know you can use this in issue creation:
await jml.issues.create({
Project: 'ENG',
'Issue Type': 'Story',
Summary: 'My Story',
[parentField.name]: 'EPIC-123', // Use discovered field name
// OR
Parent: 'EPIC-123', // "Parent" always works
});
}
// Discover parent fields for all issue types
const issueTypes = await jml.getIssueTypes('ENG');
for (const type of issueTypes) {
const parent = await jml.getParentField('ENG', type.name);
console.log(`${type.name}: ${parent?.name ?? 'No parent field'}`);
}
Validate issue data against JIRA schema without creating issues
Performs fast, schema-only validation:
Does NOT perform field name→ID lookups or value conversions. Performance target: <100ms for 100 rows.
Input options (same as create())
Validation result with errors array
// Validate before creating
const result = await jml.validate({
data: [
{ Project: 'ENG', 'Issue Type': 'Bug', Summary: 'Test' }
]
});
if (!result.valid) {
result.errors.forEach(err => {
console.error(`Row ${err.rowIndex}: ${err.field} - ${err.message}`);
});
} else {
// Validation passed, safe to create
await jml.issues.create({ data: [...] });
}
// Validate from file
const csvResult = await jml.validate({ from: 'issues.csv' });
Validate connection to JIRA
Tests the connection by fetching server info. Useful for verifying credentials and connectivity before making requests.
Server information from JIRA
if JIRA is unreachable
if credentials are invalid
const jml = new JML(config);
const serverInfo = await jml.validateConnection();
console.log(`Connected to JIRA ${serverInfo.version}`);
JIRA Magic Library - Main Class
Example