import { type Diagnostic, type File } from '@servicenow/sdk-build-core'; import { type IConnector } from './connector'; import { LazyCredential } from './credentials'; import type { Project, TransformResult } from './project'; import { type TemplateFile, type Templates } from './project-factory'; import { type TransformOptions } from './util'; /** * The Orchestrator class is responsible for managing and coordinating the lifecycle of * a project, including the build, packaging, and installation processes. */ export declare class Orchestrator { private readonly project; private readonly telemetry; private readonly credential?; private readonly connector?; constructor(project: Project, credentialOrConnector?: LazyCredential | IConnector); private getConnector; /** * Build the project, generate the output files, and save the keys registry. * * @param frozenKeys If true, an error will be thrown if any changes to the keys registry are detected. * @param skipClean If true, the build output directories will not be cleaned before building. * @param sysIds If provided, build output will only include records matching this array * @param errorOnConflict If true, sys_id conflicts between Fluent and XML will cause a build error instead of a warning * @returns The output files. */ build(options?: { frozenKeys?: boolean; sysIds?: string[] | undefined; errorOnConflict?: boolean; skipClean?: boolean; }): Promise; /** * Cleans the build appOutDir and packOutputDir of the project. */ clean(): void; /** * Generate a ZIP archive containing the project's output which can be installed with `install` method * @param packagePath The path where the ZIP archive will be saved. Defaults to `packOutputDir/{package name_version}.zip`. * @param options.skipPackageInventory If true, skips generating package_inventory.csv * @returns The path to the generated ZIP archive. */ pack(packagePath?: string, options?: { skipPackageInventory?: boolean; }): Promise; /** * Unpacks a ZIP archive containing ServiceNow application files * * @param zipPath The path to the ZIP archive. * @param targetPath The path where the files will be extracted. * @returns The list of files extracted from the ZIP archive. */ unpack(zipPath: string, targetPath: string): Promise<{ files: string[]; }>; private transform0; /** * Transforms records by table. Each chunk is one root table plus every * descendant in its relationship hierarchy — so multi-record entities * (ACL + roles, SLA + conditions, etc.) transform together. * * When `options.tables` is set, the chunk set is limited to those tables * (each expanded to its full hierarchy). Otherwise every plugin root is * processed. * * Requires `options.paths` — local transform only. */ private transformByTable; /** * For each chunk root, returns the full set of tables that belong in that * chunk (root + descendants). If `requestedTables` is given, each is * resolved via `RelationshipResolver` and keyed under its actual root — * so passing a descendant table still transforms the whole entity. */ private resolveChunkTargets; /** * Walks local XML paths, groups files by table, and yields one chunk per * root containing every file whose table is in that root's hierarchy. */ private localTableChunks; private collectLocalXmlFiles; /** * Groups XML files by the table name found in their content. * * Supports two XML formats: * - `...` * - `...` * * The table name is extracted from the first child element (e.g., ``), * not from the `table` attribute, since `` format doesn't have that attribute. * fast-xml-parser prefixes attributes with `@_`, so we skip those keys to find the * first child element name. * * Note: Composite XML files (containing multiple records from different * tables) are assigned to a single table based on the first record element. * This is acceptable because the transform pipeline handles all records in * the file regardless of this grouping — the grouping only affects which * chunk a file is processed in. */ private groupXmlFilesByTable; /** * Transforms the project's metadata files. * * @param options Options for the transform process * @returns The transformed files */ transform(options?: TransformPaths | DownloadOptions | TableTransformOptions | TransformOptions): Promise; uploadXMLFiles(filePaths: string[], options?: { targetUpdateSetId?: string; }): Promise; private downloadHostedFiles; private runPostInstallTasks; /** * Install the project on the connected ServiceNow instance. * * @param clean If true, the app will be removed from the instance before being installed again. * @param packageZipPath The path to the package zip file to install. If not provided, the project will be packed first. */ install(options?: { clean?: boolean; packageZipPath?: string; installAsStoreApp?: boolean; installAsync?: boolean; demoData?: boolean; skipFlags?: Record; }): Promise<{ trackerId?: string | undefined; rollbackId?: string | undefined; }>; /** * Generates sys_claim records on the instance to mark desired records as moved into this global app * * @param sysIds Array of sysIds to move to the app */ moveToApp(options: { sysIds: string[]; }): Promise; installConfigurations(options?: { targetUpdateSetId?: string; skipFlags?: Record; }): Promise; /** * Returns the last status of the app upgrade. */ installStatus(): Promise<{ finished: boolean; id: string; }>; /** * Download the app contents from the connected ServiceNow instance. * * @param options Options for the download process, defaults to `{ method: 'complete' }` * @param downloadPath The path where the downloaded files will be saved. Defaults to `os.tmpdir()/servicenow/download/GUID()`. * @returns The path to the downloaded zip file. */ download(options?: Exclude, downloadPath?: string): Promise; /** * Downloads and generates TypeScript type definitions for dependencies from a ServiceNow instance. * * This method can download two types of definitions: * - **Script definitions**: TypeScript definitions for ServiceNow APIs (glide.*.d.ts files) * - **Fluent types**: TypeScript definitions for configured dependencies from now.config.json * * @param options - Configuration options for what to download * @param options.downloadScripts - Download script type definitions (default: true) * @param options.downloadFluent - Download fluent type definitions from now.config.json (default: true) * * @example * ```typescript * // Download all dependencies (default) * await orchestrator.types() * * // Download only script definitions * await orchestrator.types({ downloadScripts: true, downloadFluent: false }) * * // Download only fluent types * await orchestrator.types({ downloadScripts: false, downloadFluent: true }) * ``` * * @throws {Error} If fetching or generating types fails * * @see {@link addDependency} for adding new dependencies programmatically */ types(options?: { downloadScripts?: boolean; downloadFluent?: boolean; }): Promise; /** * Adds new dependency items to the project and updates now.config.json. * * This method: * 1. Updates now.config.json with the new dependency items * 2. Fetches the records from the ServiceNow instance * 3. Generates TypeScript type definitions * 4. Updates index files * * Supports adding dependencies from any ServiceNow table, with special handling for: * - **Flow items**: actions, triggers, subflows (stored in dependencies..automation.*) * - **Tables**: Table definitions (stored in dependencies..tables) * - **Custom records**: Any other table (stored in dependencies..) * * @param options - Configuration for the dependency to add * @param options.table - Table name or alias (e.g., 'actions', 'sys_security_acl', 'sys_user') * @param options.ids - Array of sys_ids or table names. Use ['*'] to fetch all records from a scope * @param options.scope - Scope filter (e.g., 'global', 'x_my_app'). Required when using wildcard '*' * * @example * ```typescript * // Add specific flow actions * await orchestrator.addDependency({ * table: 'actions', * ids: ['action_id1', 'action_id2'] * }) * * // Add all actions from a scope using wildcard * await orchestrator.addDependency({ * table: 'actions', * ids: ['*'], * scope: 'global' * }) * * // Add specific security ACLs * await orchestrator.addDependency({ * table: 'sys_security_acl', * ids: ['acl_id1', 'acl_id2'] * }) * * // Add all ACLs from a custom scope * await orchestrator.addDependency({ * table: 'sys_security_acl', * ids: ['*'], * scope: 'x_my_app' * }) * * // Add table definitions * await orchestrator.addDependency({ * table: 'tables', * ids: ['incident', 'problem', 'change_request'] * }) * ``` * * @throws {Error} If wildcard '*' is used without a scope * @throws {Error} If fetching records from the instance fails * @throws {Error} If updating now.config.json fails * * @see {@link types} for downloading existing dependencies */ addDependency(options: { table: string; ids: string[]; scope: string; }): Promise; run(options: { script: string; }): Promise; /** * Applies a template to the project. * @param id The ID of the template to apply. * @returns The temlate files that were applied to the project */ applyTemplate(id: keyof Templates, params?: Record): Promise; /** * @deprecated Diagnostics are logged automatically */ logDiagnostics(_diagnostics: Diagnostic[], _options?: { colors?: boolean; }): void; } export type DownloadCompleteOptions = { method: 'complete'; }; export type DownloadIncrementalOptions = { method: 'incremental'; lastPull?: string; }; export type DownloadUpdateSetOptions = { method: 'update-set'; updateSetId: string; maxUpdateCount?: number; }; export type DownloadIDOptions = { method: 'sys-id'; sysIds: string[]; }; export type DownloadMetadataOptions = { method: 'metadata'; } & ({ sysId: string; table: string; } | { records: Array<{ sysId: string; table: string; }>; }); /** * Options for table-based chunked transform (local only). * Each chunk is one root table plus its descendants. */ export type TableTransformOptions = TransformOptions & { /** Table names to transform; each is expanded to its full hierarchy. */ tables: string[]; /** Local XML file(s) or directory to transform. */ paths: string | string[]; }; export type TransformPaths = TransformOptions & { paths: string[] | string; }; export type DownloadOptions = TransformOptions & (DownloadCompleteOptions | DownloadIncrementalOptions | DownloadUpdateSetOptions | DownloadMetadataOptions | DownloadIDOptions); export type BuildResult = BuildResultSuccess | BuildResultError; export type BuildResultSuccess = { success: true; files: File[]; packOutput: string; /** * @deprecated */ diagnostics: Diagnostic[]; }; export type BuildResultError = { success: false; /** * @deprecated */ diagnostics: Diagnostic[]; };