{"version":3,"file":"cli.mjs","names":["inspect","inspectDoc","_program","Logger","_spawn","join","join","NAME","fs","gzip","inspect","resampleReady","resampleWASM","gzip"],"sources":["../src/config.ts","../src/utils/format.ts","../src/utils/log.ts","../src/inspect.ts","../src/program.ts","../src/constants.ts","../src/session.ts","../src/utils/p-limit.ts","../src/utils/process.ts","../src/utils/match.ts","../src/transforms/toktx.ts","../src/transforms/ktxdecompress.ts","../src/transforms/ktxfix.ts","../src/transforms/merge.ts","../src/transforms/xmp.ts","../src/utils/gzip.ts","../src/validate.ts","../src/cli.ts"],"sourcesContent":["import { resolve } from 'node:path';\nimport type { Extension, NodeIO } from '@gltf-transform/core';\nimport { ALL_EXTENSIONS } from '@gltf-transform/extensions';\nimport draco3d from 'draco3dgltf';\nimport { MeshoptDecoder, MeshoptEncoder } from 'meshoptimizer';\nimport type { program } from './program.js';\nimport type { Session } from './session.js';\n\ninterface Config {\n\textensions: (typeof Extension)[];\n\tdependencies: Record<string, unknown>;\n\tonProgramReady?: (params: { program: typeof program; io: NodeIO; Session: typeof Session }) => Promise<void>;\n}\n\nexport type CustomConfig = Partial<Config>;\n\ntype ConfigModule = { default: CustomConfig };\n\nlet customConfigPromise: Promise<ConfigModule> | null = null;\n\nexport async function defineConfig(\n\tconfigProvider: CustomConfig | (() => Promise<CustomConfig>),\n): Promise<CustomConfig> {\n\tif (typeof configProvider === 'function') {\n\t\tconfigProvider = await configProvider();\n\t}\n\treturn configProvider;\n}\n\nexport function createDefaultConfig(): Promise<Config> {\n\treturn Promise.all([\n\t\tdraco3d.createDecoderModule(),\n\t\tdraco3d.createEncoderModule(),\n\t\tMeshoptDecoder.ready,\n\t\tMeshoptEncoder.ready,\n\t]).then(([decoder, encoder, _]) => {\n\t\treturn {\n\t\t\textensions: ALL_EXTENSIONS,\n\t\t\tdependencies: {\n\t\t\t\t'draco3d.decoder': decoder,\n\t\t\t\t'draco3d.encoder': encoder,\n\t\t\t\t'meshopt.decoder': MeshoptDecoder,\n\t\t\t\t'meshopt.encoder': MeshoptEncoder,\n\t\t\t},\n\t\t\tonProgramReady: undefined,\n\t\t};\n\t});\n}\n\nexport function loadConfig(path: string): void {\n\tpath = resolve(process.cwd(), path);\n\tpath = `file:${path}`; // Required on Windows.\n\tcustomConfigPromise = import(path).then(validateConfig) as Promise<ConfigModule>;\n}\n\nexport function validateConfig(config: CustomConfig): CustomConfig {\n\tfor (const extension of config.extensions || []) {\n\t\tif (!extension.EXTENSION_NAME) {\n\t\t\tthrow new Error('Invalid extension in config.extensions.');\n\t\t}\n\t}\n\treturn config;\n}\n\nexport async function getConfig(): Promise<Config> {\n\tconst config = await createDefaultConfig();\n\tif (customConfigPromise) {\n\t\tconst { default: customConfig } = await customConfigPromise;\n\t\tObject.assign(config, customConfig);\n\t}\n\treturn config;\n}\n","import { stripVTControlCharacters } from 'node:util';\nimport CLITable from 'cli-table3';\nimport { stringify } from 'csv-stringify';\n\nconst _longFormatter = new Intl.NumberFormat(undefined, { maximumFractionDigits: 0 });\nexport function formatLong(x: number): string {\n\treturn _longFormatter.format(x);\n}\n\nexport function formatBytes(bytes: number, decimals = 2): string {\n\tif (bytes === 0) return '0 Bytes';\n\n\tconst k = 1000;\n\tconst dm = decimals < 0 ? 0 : decimals;\n\tconst sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\n\treturn parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];\n}\n\nexport function formatParagraph(str: string): string {\n\treturn str\n\t\t.match(/.{1,80}(\\s|$)/g)!\n\t\t.map((line) => line.trim())\n\t\t.join('\\n');\n}\n\nexport function formatHeader(title: string): string {\n\treturn '' + '\\n ' + title.toUpperCase() + '\\n ────────────────────────────────────────────';\n}\n\nexport enum TableFormat {\n\tPRETTY = 'pretty',\n\tCSV = 'csv',\n\tMD = 'md',\n}\n\nconst CLI_TABLE_MARKDOWN_CHARS = {\n\ttop: '',\n\t'top-mid': '',\n\t'top-left': '',\n\t'top-right': '',\n\tbottom: '',\n\t'bottom-mid': '',\n\t'bottom-left': '',\n\t'bottom-right': '',\n\tleft: '|',\n\t'left-mid': '',\n\tmid: '',\n\t'mid-mid': '',\n\tright: '|',\n\t'right-mid': '',\n\tmiddle: '|',\n};\n\nexport async function formatTable(format: TableFormat, head: string[], rows: string[][]): Promise<string> {\n\tswitch (format) {\n\t\tcase TableFormat.PRETTY: {\n\t\t\tconst table = new CLITable({ head });\n\t\t\ttable.push(...rows);\n\t\t\treturn table.toString();\n\t\t}\n\t\tcase TableFormat.CSV:\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tstringify([head, ...rows], (err, output) => {\n\t\t\t\t\terr ? reject(err) : resolve(output);\n\t\t\t\t});\n\t\t\t});\n\t\tcase TableFormat.MD: {\n\t\t\tconst table = new CLITable({ head, chars: CLI_TABLE_MARKDOWN_CHARS });\n\t\t\ttable.push(new Array(rows[0].length).fill('---'));\n\t\t\ttable.push(...rows);\n\t\t\treturn stripVTControlCharacters(table.toString());\n\t\t}\n\t}\n}\n\nexport function formatXMP(value: string | number | boolean | Record<string, unknown> | null): string {\n\tif (!value) {\n\t\treturn '';\n\t}\n\n\tif (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n\t\treturn value.toString();\n\t}\n\n\tif (value['@list']) {\n\t\tconst list = value['@list'] as string[];\n\t\tconst hasCommas = list.some((value) => value.indexOf(',') > 0);\n\t\treturn list.join(hasCommas ? '; ' : ', ');\n\t}\n\n\tif (value['@type'] === 'rdf:Alt') {\n\t\treturn (value['rdf:_1'] as Record<string, string>)['@value'];\n\t}\n\n\treturn JSON.stringify(value);\n}\n","export let log: typeof console.log = console.log;\n\nexport function mockConsoleLog(_log: (...data: unknown[]) => void): void {\n\tlog = _log;\n}\n","import type { Document, ILogger, JSONDocument, NodeIO, WebIO } from '@gltf-transform/core';\nimport type { Packet } from '@gltf-transform/extensions';\nimport {\n\ttype InspectAnimationReport,\n\ttype InspectMaterialReport,\n\ttype InspectMeshReport,\n\ttype InspectPropertyReport,\n\ttype InspectSceneReport,\n\ttype InspectTextureReport,\n\tinspect as inspectDoc,\n} from '@gltf-transform/functions';\nimport {\n\tformatBytes,\n\tformatHeader,\n\tformatLong,\n\tformatParagraph,\n\tformatTable,\n\tformatXMP,\n\tTableFormat,\n} from './utils/format.js';\nimport { log } from './utils/log.js';\n\ntype AnyPropertyReport =\n\t| InspectSceneReport\n\t| InspectMeshReport\n\t| InspectMaterialReport\n\t| InspectTextureReport\n\t| InspectAnimationReport;\n\nexport async function inspect(\n\tjsonDoc: JSONDocument,\n\tio: NodeIO | WebIO,\n\tlogger: ILogger,\n\tformat: TableFormat,\n): Promise<void> {\n\t// Summary (does not require parsing).\n\tconst extensionsUsed = jsonDoc.json.extensionsUsed || [];\n\tconst extensionsRequired = jsonDoc.json.extensionsRequired || [];\n\tlog(formatHeader('overview'));\n\tlog(\n\t\t(await formatTable(\n\t\t\tformat,\n\t\t\t['key', 'value'],\n\t\t\t[\n\t\t\t\t['version', jsonDoc.json.asset.version],\n\t\t\t\t['generator', jsonDoc.json.asset.generator || ''],\n\t\t\t\t['extensionsUsed', extensionsUsed.join(', ') || 'none'],\n\t\t\t\t['extensionsRequired', extensionsRequired.join(', ') || 'none'],\n\t\t\t],\n\t\t)) + '\\n\\n',\n\t);\n\n\t// Parse.\n\tlet document: Document;\n\ttry {\n\t\tdocument = await io.readJSON(jsonDoc);\n\t} catch (e) {\n\t\tlogger.warn('Unable to parse document.');\n\t\tthrow e;\n\t}\n\n\t// XMP report.\n\tconst rootPacket = document.getRoot().getExtension('KHR_xmp_json_ld') as Packet | null;\n\tif (rootPacket && rootPacket.listProperties().length > 0) {\n\t\tlog(formatHeader('metadata'));\n\t\tlog(\n\t\t\t(await formatTable(\n\t\t\t\tformat,\n\t\t\t\t['key', 'value'],\n\t\t\t\trootPacket.listProperties().map((name) => [name, formatXMP(rootPacket.getProperty(name)) as string]),\n\t\t\t)) + '\\n\\n',\n\t\t);\n\t}\n\n\t// Detailed report.\n\tconst report = inspectDoc(document);\n\tawait reportSection('scenes', format, logger, report.scenes);\n\tawait reportSection('meshes', format, logger, report.meshes);\n\tawait reportSection('materials', format, logger, report.materials);\n\tawait reportSection('textures', format, logger, report.textures);\n\tawait reportSection('animations', format, logger, report.animations);\n}\n\nasync function reportSection(\n\ttype: string,\n\tformat: TableFormat,\n\tlogger: ILogger,\n\tsection: InspectPropertyReport<AnyPropertyReport>,\n) {\n\tconst properties = section.properties;\n\n\tlog(formatHeader(type));\n\tif (!properties.length) {\n\t\tlog(`No ${type} found.\\n`);\n\t\treturn;\n\t}\n\n\tconst formattedRecords = properties.map((property: AnyPropertyReport, index: number) => {\n\t\treturn formatPropertyReport(property, index, format);\n\t});\n\tconst header = Object.keys(formattedRecords[0]);\n\tconst rows = formattedRecords.map((p: Record<string, string>) => Object.values(p));\n\tconst footnotes = format !== TableFormat.CSV ? getFootnotes(type, header) : [];\n\tlog(await formatTable(format, header, rows));\n\tif (footnotes.length) log('\\n' + footnotes.join('\\n'));\n\tif (section.warnings) {\n\t\tsection.warnings.forEach((warning) => logger.warn(formatParagraph(warning)));\n\t}\n\tlog('\\n');\n}\n\nfunction formatPropertyReport(property: AnyPropertyReport, index: number, format: TableFormat): Record<string, string> {\n\tconst row: Record<string, string | number> = { '#': index };\n\tfor (const key in property) {\n\t\tconst value = (property as unknown as Record<string, string | number>)[key];\n\t\tif (Array.isArray(value)) {\n\t\t\trow[key] = value.join(', ');\n\t\t} else if (key.match(/size/i) && format !== TableFormat.CSV) {\n\t\t\trow[key] = (value as number) > 0 ? formatBytes(value as number) : '';\n\t\t} else if (typeof value === 'number') {\n\t\t\trow[key] = format !== TableFormat.CSV ? formatLong(value) : value;\n\t\t} else if (typeof value === 'boolean') {\n\t\t\trow[key] = value ? '✓' : '';\n\t\t} else {\n\t\t\trow[key] = value;\n\t\t}\n\t}\n\treturn row as Record<string, string>;\n}\n\nfunction getFootnotes(type: string, header: string[]): string[] {\n\tconst footnotes = [];\n\tif (type === 'scenes') {\n\t\tfor (let i = 0; i < header.length; i++) {\n\t\t\tif (header[i] === 'renderVertexCount') header[i] += '¹';\n\t\t\tif (header[i] === 'gpuVertexCount') header[i] += '²';\n\t\t\tif (header[i] === 'gpuNaiveVertexCount') header[i] += '³';\n\t\t}\n\t\tfootnotes.push(\n\t\t\t'¹ Expected number of vertices processed by the vertex shader for one render\\n' +\n\t\t\t\t'  pass, without considering the vertex cache.\\n',\n\t\t);\n\t\tfootnotes.push(\n\t\t\t'² Expected number of vertices uploaded to GPU, assuming each Accessor\\n' +\n\t\t\t\t'  is uploaded only once. Actual number uploaded may be higher, \\n' +\n\t\t\t\t'  dependent on the implementation and vertex buffer layout.\\n',\n\t\t);\n\t\tfootnotes.push(\n\t\t\t'³ Expected number of vertices uploaded to GPU, assuming each Primitive\\n' +\n\t\t\t\t'  is uploaded once, duplicating vertex attributes shared among Primitives.',\n\t\t);\n\t}\n\tif (type === 'meshes') {\n\t\tfor (let i = 0; i < header.length; i++) {\n\t\t\tif (header[i] === 'size') header[i] += '¹';\n\t\t}\n\t\tfootnotes.push(\n\t\t\t'⁴ size estimates GPU memory required by a mesh, in isolation. If accessors are\\n' +\n\t\t\t\t'  shared by other mesh primitives, but the meshes themselves are not reused, then\\n' +\n\t\t\t\t'  the sum of all mesh sizes will overestimate the asset\\'s total size. See \"dedup\".',\n\t\t);\n\t}\n\tif (type === 'textures') {\n\t\tfor (let i = 0; i < header.length; i++) {\n\t\t\tif (header[i] === 'gpuSize') header[i] += '⁵';\n\t\t}\n\t\tfootnotes.push(\n\t\t\t'⁵ gpuSize estimates minimum VRAM memory allocation. Older devices may require\\n' +\n\t\t\t\t'  additional memory for GPU compression formats.',\n\t\t);\n\t}\n\treturn footnotes;\n}\n","import {\n\tprogram as _program,\n\ttype Validator as CaporalValidator,\n\ttype Command,\n\ttype ParsedOption,\n\ttype Logger as WinstonLogger,\n} from '@donmccurdy/caporal';\nimport { type ILogger, Verbosity } from '@gltf-transform/core';\n\nconst PAD_EMOJI = new Set(['🫖', '🖼', '⏯']);\n\n/**********************************************************************************************\n * Program.\n */\n\nexport interface IProgram {\n\tcommand: (name: string, desc: string) => ICommand;\n\toption: (name: string, desc: string, options: IProgramOptions) => this;\n\tsection: (name: string, icon: string) => this;\n}\n\ninterface IExecOptions {\n\tsilent?: boolean;\n}\n\ninterface IInternalProgram extends IProgram {\n\tversion: (version: string) => this;\n\tdescription: (desc: string) => this;\n\tdisableGlobalOption: (name: string) => this;\n\trun: () => this;\n\texec: (args: unknown[], options?: IExecOptions) => Promise<void>;\n}\n\nexport interface IProgramOptions<T = unknown> {\n\tdefault?: T;\n\tvalidator?: CaporalValidator;\n\taction?: IActionFn;\n\thidden?: boolean;\n}\n\nexport type IActionFn = (params: {\n\targs: Record<string, unknown>;\n\toptions: Record<string, unknown>;\n\tlogger: Logger;\n}) => void;\n\nexport interface IHelpOptions {\n\tsectionName?: string;\n}\n\nclass ProgramImpl implements IInternalProgram {\n\tversion(version: string): this {\n\t\t_program.version(version);\n\t\treturn this;\n\t}\n\tdescription(desc: string): this {\n\t\t_program.description(desc);\n\t\treturn this;\n\t}\n\thelp(help: string, options?: IHelpOptions): this {\n\t\t_program.help(help, options);\n\t\treturn this;\n\t}\n\tsection(_name: string, _icon: string): this {\n\t\tconst icon = _icon + (PAD_EMOJI.has(_icon) ? ' ' : '');\n\t\tconst name = _name.toUpperCase();\n\t\tconst line = ''.padEnd(50 - name.length - 1, '─');\n\t\t_program.command('', `\\n\\n${icon} ${name} ${line}`);\n\t\treturn this;\n\t}\n\tcommand(name: string, desc: string): ICommand {\n\t\treturn new CommandImpl(_program, name, desc);\n\t}\n\toption<T>(name: string, desc: string, options: IProgramOptions<T>): this {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TODO\n\t\t_program.option(name, desc, { global: true, ...options } as any);\n\t\treturn this;\n\t}\n\tdisableGlobalOption(name: string): this {\n\t\t_program.disableGlobalOption(name);\n\t\treturn this;\n\t}\n\trun(): this {\n\t\t_program.run();\n\t\treturn this;\n\t}\n\tasync exec(args: unknown[], options?: IExecOptions): Promise<void> {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TODO\n\t\tawait _program.exec(args as any, options as any);\n\t}\n}\n\n/**********************************************************************************************\n * Command.\n */\n\nexport interface ICommand {\n\thelp: (text: string) => this;\n\targument: (name: string, desc: string) => this;\n\toption: (name: string, desc: string, options?: ICommandOptions) => this;\n\taction: (fn: IActionFn) => this;\n\talias: (name: string) => this;\n}\n\nexport interface ICommandOptions {\n\trequired?: boolean;\n\tdefault?: ParsedOption;\n\tvalidator?: CaporalValidator;\n\thidden?: boolean;\n}\n\nclass CommandImpl implements ICommand {\n\t_ctx: Command;\n\tconstructor(program: typeof _program, name: string, desc: string) {\n\t\tthis._ctx = program.command(name, desc);\n\t}\n\thelp(text: string) {\n\t\tthis._ctx.help(text);\n\t\treturn this;\n\t}\n\targument(name: string, desc: string) {\n\t\tthis._ctx.argument(name, desc);\n\t\treturn this;\n\t}\n\toption(name: string, desc: string, options?: ICommandOptions) {\n\t\tthis._ctx.option(name, desc, options);\n\t\treturn this;\n\t}\n\taction(fn: IActionFn) {\n\t\tthis._ctx.action(async (args) => {\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TODO\n\t\t\tconst logger = new Logger(args.logger as any);\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TODO\n\t\t\treturn fn({ ...args, logger } as any);\n\t\t});\n\t\treturn this;\n\t}\n\talias(name: string) {\n\t\tthis._ctx.alias(name);\n\t\treturn this;\n\t}\n}\n\nexport const program: ProgramImpl = new ProgramImpl();\n\n/**********************************************************************************************\n * Validator.\n */\n\nexport const Validator: Record<'NUMBER' | 'ARRAY' | 'BOOLEAN' | 'STRING', CaporalValidator> = {\n\tNUMBER: _program.NUMBER,\n\tARRAY: _program.ARRAY,\n\tBOOLEAN: _program.BOOLEAN,\n\tSTRING: _program.STRING,\n};\n\n/**********************************************************************************************\n * Logger.\n */\n\nexport class Logger implements ILogger {\n\t_logger: WinstonLogger;\n\t_verbosity: Verbosity;\n\tconstructor(logger: WinstonLogger) {\n\t\tthis._logger = logger;\n\n\t\tswitch (logger.level) {\n\t\t\tcase 'info':\n\t\t\t\tthis._verbosity = Verbosity.INFO;\n\t\t\t\tbreak;\n\t\t\tcase 'warn':\n\t\t\t\tthis._verbosity = Verbosity.WARN;\n\t\t\t\tbreak;\n\t\t\tcase 'error':\n\t\t\t\tthis._verbosity = Verbosity.ERROR;\n\t\t\t\tbreak;\n\t\t\tcase 'debug':\n\t\t\tdefault:\n\t\t\t\tthis._verbosity = Verbosity.DEBUG;\n\t\t}\n\t}\n\tgetVerbosity(): Verbosity {\n\t\treturn this._verbosity;\n\t}\n\tsetVerbosity(verbosity: Verbosity): void {\n\t\tswitch (verbosity) {\n\t\t\tcase Verbosity.INFO:\n\t\t\t\tthis._logger.level = 'info';\n\t\t\t\tbreak;\n\t\t\tcase Verbosity.WARN:\n\t\t\t\tthis._logger.level = 'warn';\n\t\t\t\tbreak;\n\t\t\tcase Verbosity.ERROR:\n\t\t\t\tthis._logger.level = 'error';\n\t\t\t\tbreak;\n\t\t\tcase Verbosity.DEBUG:\n\t\t\t\tthis._logger.level = 'debug';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unexpected verbosity, \"${verbosity}\".`);\n\t\t}\n\t\tthis._verbosity = verbosity;\n\t}\n\tdebug(msg: string): void {\n\t\tthis._logger.debug(msg);\n\t}\n\tinfo(msg: string): void {\n\t\tthis._logger.info(msg);\n\t}\n\twarn(msg: string): void {\n\t\tthis._logger.warn(msg);\n\t}\n\terror(msg: string): void {\n\t\tthis._logger.error(msg);\n\t}\n}\n","// Constants.\n\nexport const XMPContext: Record<string, string> = {\n\tdc: 'http://purl.org/dc/elements/1.1/',\n\tmodel3d: 'https://schema.khronos.org/model3d/xsd/1.0/',\n\trdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',\n\txmp: 'http://ns.adobe.com/xap/1.0/',\n\txmpRights: 'http://ns.adobe.com/xap/1.0/rights/',\n};\n","import { styleText } from 'node:util';\nimport { Document, FileUtils, Format, type NodeIO, type Transform, Verbosity } from '@gltf-transform/core';\nimport type { KHRXMP, Packet } from '@gltf-transform/extensions';\nimport { unpartition } from '@gltf-transform/functions';\nimport { Listr, type ListrTask } from 'listr2';\nimport { XMPContext } from './constants.js';\nimport type { Logger } from './program.js';\nimport { formatBytes, formatLong } from './utils/format.js';\n\n/** Helper class for managing a CLI command session. */\nexport class Session {\n\tprivate _outputFormat: Format;\n\tprivate _display = false;\n\n\tconstructor(\n\t\tprivate _io: NodeIO,\n\t\tprivate _logger: Logger,\n\t\tprivate _input: string,\n\t\tprivate _output: string,\n\t) {\n\t\t_io.setLogger(_logger);\n\t\tthis._outputFormat = FileUtils.extension(_output) === 'glb' ? Format.GLB : Format.GLTF;\n\t}\n\n\tpublic static create(io: NodeIO, logger: Logger, input: unknown, output: unknown): Session {\n\t\treturn new Session(io, logger, input as string, output as string);\n\t}\n\n\tpublic setDisplay(display: boolean): this {\n\t\tthis._display = display;\n\t\treturn this;\n\t}\n\n\tpublic async transform(...transforms: Transform[]): Promise<void> {\n\t\tconst logger = this._logger;\n\t\tconst document = this._input\n\t\t\t? (await this._io.read(this._input)).setLogger(this._logger)\n\t\t\t: new Document().setLogger(this._logger);\n\n\t\t// Warn and remove lossy compression, to avoid increasing loss on round trip.\n\t\tfor (const extensionName of ['KHR_draco_mesh_compression', 'EXT_meshopt_compression']) {\n\t\t\tif (document.hasExtension(extensionName)) {\n\t\t\t\tdocument.disposeExtension(extensionName);\n\t\t\t\tthis._logger.warn(`Decoded ${extensionName}. Further compression will be lossy.`);\n\t\t\t}\n\t\t}\n\n\t\tif (this._display) {\n\t\t\tconst tasks = [] as ListrTask[];\n\t\t\tfor (const transform of transforms) {\n\t\t\t\ttasks.push({\n\t\t\t\t\ttitle: transform.name,\n\t\t\t\t\ttask: async (_ctx, task) => {\n\t\t\t\t\t\tlet time = performance.now();\n\t\t\t\t\t\tawait document.transform(transform);\n\t\t\t\t\t\ttime = Math.round(performance.now() - time);\n\t\t\t\t\t\ttask.title = task.title.padEnd(20) + styleText('dim', ` ${formatLong(time)}ms`);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst prevLevel = logger.getVerbosity();\n\t\t\tif (prevLevel === Verbosity.INFO) logger.setVerbosity(Verbosity.WARN);\n\n\t\t\t// Disable signal listeners so Ctrl+C works. Note that 'simple' and 'default'\n\t\t\t// renderers have different capability to display errors and warnings.\n\t\t\tawait new Listr(tasks, {\n\t\t\t\trenderer: 'default',\n\t\t\t\tregisterSignalListeners: false,\n\t\t\t\tsilentRendererCondition: process.env.NODE_ENV === 'test',\n\t\t\t}).run();\n\t\t\tconsole.log('');\n\n\t\t\tlogger.setVerbosity(prevLevel);\n\t\t} else {\n\t\t\tawait document.transform(...transforms);\n\t\t}\n\n\t\tawait document.transform(updateMetadata);\n\n\t\tif (this._outputFormat === Format.GLB) {\n\t\t\tawait document.transform(unpartition());\n\t\t}\n\n\t\tawait this._io.write(this._output, document);\n\n\t\tconst { lastReadBytes, lastWriteBytes } = this._io;\n\t\tif (!this._input) {\n\t\t\tconst output = FileUtils.basename(this._output) + '.' + FileUtils.extension(this._output);\n\t\t\tthis._logger.info(`${output} (${formatBytes(lastWriteBytes)})`);\n\t\t} else {\n\t\t\tconst input = FileUtils.basename(this._input) + '.' + FileUtils.extension(this._input);\n\t\t\tconst output = FileUtils.basename(this._output) + '.' + FileUtils.extension(this._output);\n\t\t\tthis._logger.info(\n\t\t\t\t`${input} (${formatBytes(lastReadBytes)})` + ` → ${output} (${formatBytes(lastWriteBytes)})`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction updateMetadata(document: Document): void {\n\tconst root = document.getRoot();\n\tconst xmpExtension = root\n\t\t.listExtensionsUsed()\n\t\t.find((ext) => ext.extensionName === 'KHR_xmp_json_ld') as KHRXMP | null;\n\n\t// Do not add KHR_xmp_json_ld to assets that don't already use it.\n\tif (!xmpExtension) return;\n\n\tconst rootPacket = root.getExtension<Packet>('KHR_xmp_json_ld') || xmpExtension.createPacket();\n\n\t// xmp:MetadataDate should be the same as, or more recent than, xmp:ModifyDate.\n\t// https://github.com/adobe/xmp-docs/blob/master/XMPNamespaces/xmp.md\n\tconst date = new Date().toISOString().substring(0, 10);\n\trootPacket\n\t\t.setContext({ ...rootPacket.getContext(), xmp: XMPContext.xmp })\n\t\t.setProperty('xmp:ModifyDate', date)\n\t\t.setProperty('xmp:MetadataDate', date);\n}\n","type PLimitFn<T> = ((value: T, index: number) => Promise<void>) | ((value: T, index: number) => void);\n\n/** Runs multiple async functions, with limited concurrency. */\nexport async function pLimit<T>(items: T[], limit: number, fn: PLimitFn<T>): Promise<void> {\n\t// Iterate values in order, 0–N.\n\titems = items.slice().reverse();\n\n\tlet index = 0;\n\n\t// Spawn 'limit' concurrent functions.\n\tawait Promise.all(\n\t\t[...Array(limit)].map(async () => {\n\t\t\twhile (items.length > 0) {\n\t\t\t\tawait fn(items.pop()!, index++);\n\t\t\t}\n\t\t}),\n\t);\n}\n","import type { ChildProcess } from 'node:child_process';\nimport { spawn as _spawn, execSync } from 'node:child_process';\nimport { access, constants } from 'node:fs/promises';\n\n// Mocks for tests.\n\nexport let spawn: typeof _spawn = _spawn;\nexport let commandExists: typeof _commandExists = _commandExists;\nexport let waitExit: typeof _waitExit = _waitExit;\n\nexport function mockSpawn(_spawn: unknown): void {\n\tspawn = _spawn as typeof spawn;\n}\n\nexport function mockCommandExists(fn: (n: TrustedCommand) => Promise<boolean>): void {\n\tcommandExists = fn as unknown as typeof _commandExists;\n}\n\nexport function mockWaitExit(_waitExit: (process: ChildProcess) => Promise<[unknown, string, string]>): void {\n\twaitExit = _waitExit;\n}\n\nexport enum TrustedCommand {\n\tKTX = 'ktx',\n}\n\n/**\n * Resolves 'true' if an executable command-line command with the given name\n * exists, otherwise returns false. This is a stripped-down version of the\n * npm package, `command-exists` (https://github.com/mathisonian/command-exists).\n */\nasync function _commandExists(cmd: TrustedCommand): Promise<boolean> {\n\tif (process.platform === 'win32') {\n\t\ttry {\n\t\t\treturn !!execSync(`where ${cmd}`);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst isFile = await access(cmd, constants.F_OK)\n\t\t.then(() => true)\n\t\t.catch(() => false);\n\n\tif (!isFile) {\n\t\tconst versionCmd = `command -v ${cmd} 2>/dev/null && { echo >&1 ${cmd}; exit 0; }`;\n\t\treturn !!execSync(versionCmd, { encoding: 'utf8' });\n\t}\n\n\tconst isExecutable = access(cmd, constants.F_OK | constants.X_OK)\n\t\t.then(() => true)\n\t\t.catch(() => false);\n\n\treturn isExecutable;\n}\n\nexport async function _waitExit(process: ChildProcess): Promise<[unknown, string, string]> {\n\tlet stdout = '';\n\tif (process.stdout) {\n\t\tfor await (const chunk of process.stdout) {\n\t\t\tstdout += chunk;\n\t\t}\n\t}\n\tlet stderr = '';\n\tif (process.stderr) {\n\t\tfor await (const chunk of process.stderr) {\n\t\t\tstderr += chunk;\n\t\t}\n\t}\n\tconst status = await new Promise((resolve, _) => {\n\t\tprocess.on('close', resolve);\n\t});\n\treturn [status, stdout, stderr];\n}\n","import micromatch from 'micromatch';\n\n// Using 'micromatch' because 'contains: true' did not work as expected with\n// minimatch. Need to ensure that '*' matches patterns like 'image/png'.\nexport const MICROMATCH_OPTIONS = { nocase: true, contains: true };\n\n// See: https://github.com/micromatch/micromatch/issues/224\nexport function regexFromArray(values: string[]): RegExp {\n\tconst pattern = values.map((s) => `(${s})`).join('|');\n\treturn micromatch.makeRe(pattern, MICROMATCH_OPTIONS);\n}\n","import fs, { rm } from 'node:fs/promises';\nimport os from 'node:os';\nimport { join } from 'node:path';\nimport {\n\tBufferUtils,\n\ttype Document,\n\tFileUtils,\n\ttype ILogger,\n\tImageUtils,\n\ttype Texture,\n\tTextureChannel,\n\tTextureInfo,\n\ttype Transform,\n\tuuid,\n\ttype vec2,\n} from '@gltf-transform/core';\nimport { KHRTextureBasisu } from '@gltf-transform/extensions';\nimport {\n\tcreateTransform,\n\tfitPowerOfTwo,\n\tfitWithin,\n\tgetTextureChannelMask,\n\tgetTextureColorSpace,\n\tlistTextureInfo,\n\tlistTextureSlots,\n\tTextureResizeFilter,\n} from '@gltf-transform/functions';\nimport micromatch from 'micromatch';\nimport type sharp from 'sharp';\nimport tmp from 'tmp';\nimport { formatBytes } from '../utils/format.js';\nimport { MICROMATCH_OPTIONS } from '../utils/match.js';\nimport { pLimit } from '../utils/p-limit.js';\nimport { commandExists, spawn, TrustedCommand, waitExit } from '../utils/process.js';\n\nconst NUM_CPUS = os.cpus().length || 1; // microsoft/vscode#112122\n\n// Options for specifying transfer functions refactored in v4.4.\n// https://github.com/KhronosGroup/KTX-Software/releases#release-v4.4.0\nconst KTX_SOFTWARE_VERSION_MIN = '4.4.0';\n\nconst { R, G, A } = TextureChannel;\nconst { NEAREST, NEAREST_MIPMAP_LINEAR, NEAREST_MIPMAP_NEAREST, LINEAR, LINEAR_MIPMAP_NEAREST } = TextureInfo.MinFilter;\n\n/**********************************************************************************************\n * Interfaces.\n */\n\nexport const Mode = {\n\tETC1S: 'etc1s',\n\tUASTC: 'uastc',\n};\n\nexport const Filter = {\n\tBOX: 'box',\n\tTENT: 'tent',\n\tBELL: 'bell',\n\tBSPLINE: 'b-spline',\n\tMITCHELL: 'mitchell',\n\tLANCZOS3: 'lanczos3',\n\tLANCZOS4: 'lanczos4',\n\tLANCZOS6: 'lanczos6',\n\tLANCZOS12: 'lanczos12',\n\tBLACKMAN: 'blackman',\n\tKAISER: 'kaiser',\n\tGAUSSIAN: 'gaussian',\n\tCATMULLROM: 'catmullrom',\n\tQUADRATIC_INTERP: 'quadratic_interp',\n\tQUADRATIC_APPROX: 'quadratic_approx',\n\tQUADRATIC_MIX: 'quadratic_mix',\n};\n\ninterface GlobalOptions {\n\t/** Instance of the Sharp encoder, required if resizing textures. */\n\tencoder: unknown;\n\tmode: string;\n\t/** Pattern identifying textures to compress, matched to name or URI. */\n\tpattern?: RegExp | null;\n\t/**\n\t * Pattern matching the material texture slot(s) to be compressed or converted.\n\t * Passing a string (glob) is deprecated; use a RegExp instead.\n\t */\n\tslots?: RegExp | null;\n\t/** Interpolation used for generating mipmaps. Default: 'lanczos4'. */\n\tfilter?: string;\n\tfilterScale?: number;\n\tresize?: vec2 | 'nearest-pot' | 'ceil-pot' | 'floor-pot';\n\t/** Interpolation used if resizing. Default: TextureResizeFilter.LANCZOS3. */\n\tresizeFilter?: TextureResizeFilter;\n\tjobs?: number;\n\t/**\n\t * Whether to clean up temporary files created during texture compression. See\n\t * verbose log output for temporary file paths. Default: true.\n\t */\n\tcleanup?: boolean;\n\t/**\n\t * Attempts to avoid processing images that could exceed memory or other other\n\t * limits, throwing an error instead. Default: true.\n\t * @experimental\n\t */\n\tlimitInputPixels?: boolean;\n\t/** Whether to generate mipmaps. Default: true. */\n\tmipmaps?: boolean;\n}\n\nexport interface ETC1SOptions extends GlobalOptions {\n\tquality?: number;\n\tcompression?: number;\n\tmaxEndpoints?: number;\n\tmaxSelectors?: number;\n\trdo?: boolean;\n\trdoThreshold?: number;\n}\n\nexport interface UASTCOptions extends GlobalOptions {\n\tlevel?: number;\n\trdo?: boolean;\n\trdoLambda?: number;\n\trdoDictionarySize?: number;\n\trdoBlockScale?: number;\n\trdoStdDev?: number;\n\trdoMultithreading?: boolean;\n\tzstd?: number;\n}\n\nconst GLOBAL_DEFAULTS: Omit<GlobalOptions, 'encoder' | 'mode'> = {\n\tresizeFilter: TextureResizeFilter.LANCZOS3,\n\tfilter: Filter.LANCZOS4,\n\tfilterScale: 1,\n\tpattern: null,\n\tslots: null,\n\t// See: https://github.com/donmccurdy/glTF-Transform/pull/389#issuecomment-1089842185\n\tjobs: 2 * NUM_CPUS,\n\tcleanup: true,\n\tlimitInputPixels: true,\n\tmipmaps: true,\n};\n\nexport const ETC1S_DEFAULTS: Omit<ETC1SOptions, 'encoder' | 'mode'> = {\n\tquality: 128,\n\tcompression: 1,\n\trdo: true,\n\trdoThreshold: 1.25,\n\tmaxSelectors: 0,\n\tmaxEndpoints: 0,\n\t...GLOBAL_DEFAULTS,\n};\n\nexport const UASTC_DEFAULTS: Omit<UASTCOptions, 'encoder' | 'mode'> = {\n\tlevel: 2,\n\trdo: false,\n\trdoLambda: 1.0,\n\trdoDictionarySize: 32768,\n\trdoBlockScale: 10.0,\n\trdoStdDev: 18.0,\n\trdoMultithreading: true,\n\tzstd: 18,\n\t...GLOBAL_DEFAULTS,\n};\n\n/**********************************************************************************************\n * Implementation.\n */\n\nexport const toktx = function (options: ETC1SOptions | UASTCOptions): Transform {\n\toptions = {\n\t\t...(options.mode === Mode.ETC1S ? ETC1S_DEFAULTS : UASTC_DEFAULTS),\n\t\t...options,\n\t};\n\n\treturn createTransform(options.mode, async (doc: Document): Promise<void> => {\n\t\tconst logger = doc.getLogger();\n\n\t\t// Confirm recent version of KTX-Software is installed.\n\t\tawait checkKTXSoftware(logger);\n\n\t\t// Create workspace. Avoid 'unsafeCleanup' and 'setGracefulCleanup', which\n\t\t// are not working as expected and are slated for removal:\n\t\t// https://github.com/raszi/node-tmp/pull/281\n\t\tconst batchPrefix = uuid();\n\t\tconst batchDir = tmp.dirSync({ prefix: 'gltf-transform-' });\n\n\t\tconst basisuExtension = doc.createExtension(KHRTextureBasisu).setRequired(true);\n\n\t\tconst textures = doc.getRoot().listTextures();\n\t\tconst numTextures = textures.length;\n\n\t\tawait pLimit(textures, options.jobs!, async (texture, textureIndex) => {\n\t\t\tconst slots = listTextureSlots(texture);\n\t\t\tconst channels = getTextureChannelMask(texture);\n\t\t\tconst textureLabel =\n\t\t\t\ttexture.getURI() || texture.getName() || `${textureIndex + 1}/${doc.getRoot().listTextures().length}`;\n\t\t\tconst prefix = `ktx:texture(${textureLabel})`;\n\t\t\tlogger.debug(`${prefix}: Slots → [${slots.join(', ')}]`);\n\n\t\t\t// FILTER: Exclude textures that don't match (a) 'slots' or (b) expected formats.\n\n\t\t\tif (typeof options.slots === 'string') {\n\t\t\t\toptions.slots = micromatch.makeRe(options.slots, MICROMATCH_OPTIONS);\n\t\t\t\tlogger.warn('ktx: Argument \"slots\" should be of type `RegExp | null`.');\n\t\t\t}\n\n\t\t\tconst patternRe = options.pattern as RegExp | null;\n\t\t\tconst slotsRe = options.slots as RegExp | null;\n\n\t\t\tlet srcMimeType = texture.getMimeType();\n\n\t\t\tif (srcMimeType === 'image/ktx2') {\n\t\t\t\tlogger.debug(`${prefix}: Skipping, already KTX.`);\n\t\t\t\treturn;\n\t\t\t} else if (srcMimeType !== 'image/png' && srcMimeType !== 'image/jpeg') {\n\t\t\t\tlogger.warn(`${prefix}: Skipping, unsupported texture type \"${texture.getMimeType()}\".`);\n\t\t\t\treturn;\n\t\t\t} else if (slotsRe && !slots.find((slot) => slot.match(slotsRe))) {\n\t\t\t\tlogger.debug(`${prefix}: Skipping, [${slots.join(', ')}] excluded by \"slots\" parameter.`);\n\t\t\t\treturn;\n\t\t\t} else if (patternRe && !(texture.getURI().match(patternRe) || texture.getName().match(patternRe))) {\n\t\t\t\tlogger.debug(`${prefix}: Skipping, excluded by \"pattern\" parameter.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet srcImage = texture.getImage()!;\n\t\t\tlet srcExtension = texture.getURI()\n\t\t\t\t? FileUtils.extension(texture.getURI())\n\t\t\t\t: ImageUtils.mimeTypeToExtension(texture.getMimeType());\n\t\t\tconst srcSize = texture.getSize();\n\t\t\tconst srcBytes = srcImage ? srcImage.byteLength : null;\n\n\t\t\tif (!srcImage || !srcSize || !srcBytes) {\n\t\t\t\tlogger.warn(`${prefix}: Skipping, unreadable texture.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// RESIZE: Resize textures using Sharp. KTX Software --width and --height\n\t\t\t// flags apply only for raw texture creation.\n\t\t\t// https://github.com/donmccurdy/glTF-Transform/issues/1348\n\t\t\t//\n\t\t\t// Minimum size on any dimension is 4px.\n\t\t\t// https://github.com/donmccurdy/glTF-Transform/issues/502\n\n\t\t\tif (options.resize || !isMultipleOfFour(srcSize[0]) || !isMultipleOfFour(srcSize[1])) {\n\t\t\t\tconst limitInputPixels = options.limitInputPixels;\n\t\t\t\tconst encoder = options.encoder as typeof sharp;\n\t\t\t\tconst instance = encoder(srcImage, { limitInputPixels }).toFormat('png');\n\t\t\t\tconst srcSize = ImageUtils.getSize(srcImage, srcMimeType)!;\n\n\t\t\t\tconst dstSize = options.resize\n\t\t\t\t\t? Array.isArray(options.resize)\n\t\t\t\t\t\t? fitWithin(srcSize, options.resize)\n\t\t\t\t\t\t: fitPowerOfTwo(srcSize, options.resize)\n\t\t\t\t\t: srcSize;\n\t\t\t\tdstSize[0] = ceilMultipleOfFour(dstSize[0]);\n\t\t\t\tdstSize[1] = ceilMultipleOfFour(dstSize[1]);\n\n\t\t\t\tlogger.debug(`${prefix}: Resizing ${srcSize.join('x')} → ${dstSize.join('x')}px`);\n\t\t\t\tinstance.resize(dstSize[0], dstSize[1], { fit: 'fill', kernel: options.resizeFilter });\n\n\t\t\t\tsrcImage = BufferUtils.toView((await instance.toBuffer()) as Buffer<ArrayBuffer>);\n\t\t\t\tsrcExtension = 'png';\n\t\t\t\tsrcMimeType = 'image/png';\n\t\t\t}\n\n\t\t\t// PREPARE: Create temporary in/out paths for the 'ktx' CLI tool, and determine\n\t\t\t// necessary command-line flags.\n\n\t\t\tconst srcPath = join(batchDir.name, `${batchPrefix}_${textureIndex}.${srcExtension}`);\n\t\t\tconst dstPath = join(batchDir.name, `${batchPrefix}_${textureIndex}.ktx2`);\n\n\t\t\tawait fs.writeFile(srcPath, srcImage);\n\n\t\t\tconst params = [\n\t\t\t\t'create',\n\t\t\t\t...createParams(texture, slots, channels, numTextures, options),\n\t\t\t\tsrcPath,\n\t\t\t\tdstPath,\n\t\t\t];\n\t\t\tlogger.debug(`${prefix}: Spawning → ktx ${params.join(' ')}`);\n\n\t\t\t// COMPRESS: Run `ktx create` CLI tool.\n\t\t\tconst [status, _stdout, stderr] = await waitExit(spawn('ktx', params as string[]));\n\n\t\t\tif (status !== 0) {\n\t\t\t\tlogger.error(`${prefix}: Failed → \\n\\n${stderr.toString()}`);\n\t\t\t} else {\n\t\t\t\t// PACK: Replace image data in the glTF asset.\n\t\t\t\ttexture.setImage(await fs.readFile(dstPath)).setMimeType('image/ktx2');\n\t\t\t\tif (texture.getURI()) {\n\t\t\t\t\ttexture.setURI(FileUtils.basename(texture.getURI()) + '.ktx2');\n\t\t\t\t}\n\n\t\t\t\t// When mipmaps are disabled, downgrade mipmap filters to non-mipmap equivalents.\n\t\t\t\tif (!options.mipmaps) {\n\t\t\t\t\tfor (const info of listTextureInfo(texture)) {\n\t\t\t\t\t\tconst minFilter = info.getMinFilter();\n\t\t\t\t\t\tif (minFilter === NEAREST_MIPMAP_LINEAR || minFilter === NEAREST_MIPMAP_NEAREST) {\n\t\t\t\t\t\t\tinfo.setMinFilter(NEAREST);\n\t\t\t\t\t\t} else if (minFilter === LINEAR_MIPMAP_NEAREST) {\n\t\t\t\t\t\t\tinfo.setMinFilter(LINEAR);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst dstBytes = texture.getImage()!.byteLength;\n\t\t\tlogger.debug(`${prefix}: ${formatBytes(srcBytes)} → ${formatBytes(dstBytes)} bytes`);\n\t\t});\n\n\t\tif (options.cleanup) {\n\t\t\tawait rm(batchDir.name, { recursive: true });\n\t\t}\n\n\t\tconst usesKTX2 = doc\n\t\t\t.getRoot()\n\t\t\t.listTextures()\n\t\t\t.some((t) => t.getMimeType() === 'image/ktx2');\n\n\t\tif (!usesKTX2) {\n\t\t\tbasisuExtension.dispose();\n\t\t}\n\t});\n};\n\n/**********************************************************************************************\n * Utilities.\n */\n\n/** Create CLI parameters from the given options. Attempts to write only non-default options. */\nfunction createParams(\n\ttexture: Texture,\n\tslots: string[],\n\tchannels: number,\n\tnumTextures: number,\n\toptions: ETC1SOptions | UASTCOptions,\n): (string | number)[] {\n\tconst colorSpace = getTextureColorSpace(texture);\n\tconst params: (string | number)[] = [];\n\n\tif (options.mipmaps) {\n\t\tparams.push('--generate-mipmap');\n\t}\n\n\tif (options.mipmaps && options.filter !== GLOBAL_DEFAULTS.filter) {\n\t\tparams.push('--mipmap-filter', options.filter!);\n\t}\n\n\tif (options.mipmaps && options.filterScale !== GLOBAL_DEFAULTS.filterScale) {\n\t\tparams.push('--mipmap-filter-scale', options.filterScale!);\n\t}\n\n\t// See: https://github.com/KhronosGroup/KTX-Software/issues/600\n\tconst isNormalMap = slots.find((slot) => micromatch.isMatch(slot, '*normal*', MICROMATCH_OPTIONS));\n\n\tif (options.mode === Mode.UASTC) {\n\t\tconst _options = options as UASTCOptions;\n\t\tparams.push('--encode', 'uastc');\n\t\tparams.push('--uastc-quality', _options.level!);\n\n\t\tif (_options.rdo && !isNormalMap) {\n\t\t\tparams.push('--uastc-rdo');\n\t\t\tif (_options.rdoLambda !== UASTC_DEFAULTS.rdoLambda) {\n\t\t\t\tparams.push('--uastc-rdo-l', _options.rdoLambda!);\n\t\t\t}\n\t\t\tif (_options.rdoDictionarySize !== UASTC_DEFAULTS.rdoDictionarySize) {\n\t\t\t\tparams.push('--uastc-rdo-d', _options.rdoDictionarySize!);\n\t\t\t}\n\t\t\tif (_options.rdoBlockScale !== UASTC_DEFAULTS.rdoBlockScale) {\n\t\t\t\tparams.push('--uastc-rdo-b', _options.rdoBlockScale!);\n\t\t\t}\n\t\t\tif (_options.rdoStdDev !== UASTC_DEFAULTS.rdoStdDev) {\n\t\t\t\tparams.push('--uastc-rdo-s', _options.rdoStdDev!);\n\t\t\t}\n\t\t\tif (!_options.rdoMultithreading) {\n\t\t\t\tparams.push('--uastc-rdo-m');\n\t\t\t}\n\t\t}\n\n\t\tif (_options.zstd && _options.zstd > 0) {\n\t\t\tparams.push('--zstd', _options.zstd);\n\t\t}\n\t} else {\n\t\tconst _options = options as ETC1SOptions;\n\t\tparams.push('--encode', 'basis-lz');\n\n\t\tif (_options.quality !== ETC1S_DEFAULTS.quality) {\n\t\t\tparams.push('--qlevel', _options.quality!);\n\t\t}\n\t\tif (_options.compression !== ETC1S_DEFAULTS.compression) {\n\t\t\tparams.push('--clevel', _options.compression!);\n\t\t}\n\t\tif (_options.rdo && !isNormalMap) {\n\t\t\tif (_options.maxEndpoints !== ETC1S_DEFAULTS.maxEndpoints) {\n\t\t\t\tparams.push('--max-endpoints', _options.maxEndpoints!);\n\t\t\t}\n\t\t\tif (_options.maxSelectors !== ETC1S_DEFAULTS.maxSelectors) {\n\t\t\t\tparams.push('--max-selectors', _options.maxSelectors!);\n\t\t\t}\n\t\t\tif (_options.rdoThreshold !== ETC1S_DEFAULTS.rdoThreshold) {\n\t\t\t\tparams.push('--endpoint-rdo-threshold', _options.rdoThreshold!);\n\t\t\t\tparams.push('--selector-rdo-threshold', _options.rdoThreshold!);\n\t\t\t}\n\t\t} else {\n\t\t\tparams.push('--no-endpoint-rdo', '--no-selector-rdo');\n\t\t}\n\t}\n\n\t// See: https://github.com/donmccurdy/glTF-Transform/issues/215\n\tif (colorSpace === 'srgb') {\n\t\tparams.push('--assign-tf', 'srgb', '--assign-primaries', 'bt709');\n\t} else if (colorSpace === 'srgb-linear') {\n\t\tparams.push('--assign-tf', 'linear', '--assign-primaries', 'bt709');\n\t} else if (slots.length && !colorSpace) {\n\t\tparams.push('--assign-tf', 'linear', '--assign-primaries', 'none');\n\t}\n\n\tif (channels === R) {\n\t\tparams.push('--format', 'R8_UNORM');\n\t} else if (channels === G || channels === (R | G)) {\n\t\tparams.push('--format', 'R8G8_UNORM');\n\t} else if (!(channels & A)) {\n\t\tparams.push('--format', colorSpace === 'srgb' ? 'R8G8B8_SRGB' : 'R8G8B8_UNORM');\n\t} else {\n\t\tparams.push('--format', colorSpace === 'srgb' ? 'R8G8B8A8_SRGB' : 'R8G8B8A8_UNORM');\n\t}\n\n\tif (options.jobs && options.jobs > 1 && numTextures > 1) {\n\t\t// See: https://github.com/donmccurdy/glTF-Transform/pull/389#issuecomment-1089842185\n\t\tconst threads = Math.max(2, Math.min(NUM_CPUS, Math.round((3 * NUM_CPUS) / numTextures)));\n\t\tparams.push('--threads', threads);\n\t}\n\n\treturn params;\n}\n\nexport async function checkKTXSoftware(logger: ILogger): Promise<string> {\n\tif (!(await commandExists(TrustedCommand.KTX)) && !process.env.CI) {\n\t\tthrow new Error(\n\t\t\t`Command \"ktx\" not found. Please install KTX-Software ${KTX_SOFTWARE_VERSION_MIN}+, ` +\n\t\t\t\t'from:\\n\\nhttps://github.com/KhronosGroup/KTX-Software',\n\t\t);\n\t}\n\n\tconst [status, stdout, stderr] = await waitExit(spawn('ktx', ['--version']));\n\n\tconst version = ((stdout || stderr) as string)\n\t\t.replace(/ktx version:\\s+/, '')\n\t\t.replace(/~\\d+/, '')\n\t\t.trim();\n\n\tif (status !== 0 || !version) {\n\t\tthrow new Error(\n\t\t\t`Unable to find \"ktx\" version. Confirm KTX-Software ${KTX_SOFTWARE_VERSION_MIN}+ is installed.`,\n\t\t);\n\t} else {\n\t\tlogger.debug(`ktx: Found KTX-Software ${version}.`);\n\t}\n\n\treturn version;\n}\n\nfunction isMultipleOfFour(value: number): boolean {\n\treturn value % 4 === 0;\n}\n\nfunction ceilMultipleOfFour(value: number): number {\n\tif (value <= 4) return 4;\n\treturn 4 * Math.ceil(value / 4);\n}\n","import fs, { rm } from 'node:fs/promises';\nimport os from 'node:os';\nimport { join } from 'node:path';\nimport { type Document, FileUtils, ImageUtils, type Transform, uuid } from '@gltf-transform/core';\nimport { KHRTextureBasisu } from '@gltf-transform/extensions';\nimport { createTransform } from '@gltf-transform/functions';\nimport tmp from 'tmp';\nimport { formatBytes } from '../utils/format.js';\nimport { pLimit } from '../utils/p-limit.js';\nimport { spawn, waitExit } from '../utils/process.js';\nimport { checkKTXSoftware } from './toktx.js';\n\nconst NUM_CPUS = os.cpus().length || 1; // microsoft/vscode#112122\n\ninterface KTXDecompressOptions {\n\tjobs?: number;\n\t/**\n\t * Whether to clean up temporary files created during texture compression. See\n\t * verbose log output for temporary file paths. Default: true.\n\t */\n\tcleanup?: boolean;\n}\n\nconst KTX_DECOMPRESS_DEFAULTS: KTXDecompressOptions = {\n\t// See: https://github.com/donmccurdy/glTF-Transform/pull/389#issuecomment-1089842185\n\tjobs: 2 * NUM_CPUS,\n\tcleanup: true,\n};\n\nexport const ktxdecompress = function (options: KTXDecompressOptions = KTX_DECOMPRESS_DEFAULTS): Transform {\n\toptions = { ...KTX_DECOMPRESS_DEFAULTS, ...options };\n\n\treturn createTransform('ktxdecompress', async (doc: Document): Promise<void> => {\n\t\tconst logger = doc.getLogger();\n\n\t\t// Confirm recent version of KTX-Software is installed.\n\t\tawait checkKTXSoftware(logger);\n\n\t\t// Create workspace. Avoid 'unsafeCleanup' and 'setGracefulCleanup', which\n\t\t// are not working as expected and are slated for removal:\n\t\t// https://github.com/raszi/node-tmp/pull/281\n\t\tconst batchPrefix = uuid();\n\t\tconst batchDir = tmp.dirSync({ prefix: 'gltf-transform-' });\n\n\t\tconst basisuExtension = doc.createExtension(KHRTextureBasisu);\n\t\tconst textures = doc.getRoot().listTextures();\n\n\t\tawait pLimit(textures, options.jobs!, async (texture, textureIndex) => {\n\t\t\tconst textureLabel =\n\t\t\t\ttexture.getURI() || texture.getName() || `${textureIndex + 1}/${doc.getRoot().listTextures().length}`;\n\t\t\tconst prefix = `ktx:texture(${textureLabel})`;\n\n\t\t\tconst srcMimeType = texture.getMimeType();\n\t\t\tif (srcMimeType !== 'image/ktx2') return;\n\n\t\t\tconst srcImage = texture.getImage()!;\n\t\t\tconst srcExtension = texture.getURI()\n\t\t\t\t? FileUtils.extension(texture.getURI())\n\t\t\t\t: ImageUtils.mimeTypeToExtension(srcMimeType);\n\t\t\tconst srcSize = texture.getSize();\n\t\t\tconst srcBytes = srcImage ? srcImage.byteLength : null;\n\n\t\t\tif (!srcImage || !srcSize || !srcBytes) {\n\t\t\t\tlogger.warn(`${prefix}: Skipping, unreadable texture.`);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// PREPARE: Create temporary in/out paths for the 'ktx' CLI tool, and determine\n\t\t\t// necessary command-line flags.\n\n\t\t\tconst srcPath = join(batchDir.name, `${batchPrefix}_${textureIndex}.${srcExtension}`);\n\t\t\tconst dstPath = join(batchDir.name, `${batchPrefix}_${textureIndex}.png`);\n\n\t\t\tawait fs.writeFile(srcPath, srcImage);\n\n\t\t\t// COMPRESS: Run `ktx create` CLI tool.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t\t\tconst [status, _stdout, stderr] = await waitExit(spawn('ktx', ['extract', srcPath, dstPath]));\n\n\t\t\tif (status !== 0) {\n\t\t\t\tlogger.error(`${prefix}: Failed → \\n\\n${stderr.toString()}`);\n\t\t\t} else {\n\t\t\t\t// PACK: Replace image data in the glTF asset.\n\t\t\t\ttexture.setImage(await fs.readFile(dstPath)).setMimeType('image/png');\n\t\t\t\tif (texture.getURI()) {\n\t\t\t\t\ttexture.setURI(FileUtils.basename(texture.getURI()) + '.png');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst dstBytes = texture.getImage()!.byteLength;\n\t\t\tlogger.debug(`${prefix}: ${formatBytes(srcBytes)} → ${formatBytes(dstBytes)} bytes`);\n\t\t});\n\n\t\tif (options.cleanup) {\n\t\t\tawait rm(batchDir.name, { recursive: true });\n\t\t}\n\n\t\tconst usesKTX2 = doc\n\t\t\t.getRoot()\n\t\t\t.listTextures()\n\t\t\t.some((t) => t.getMimeType() === 'image/ktx2');\n\n\t\tif (!usesKTX2) {\n\t\t\tbasisuExtension.dispose();\n\t\t}\n\t});\n};\n","import type { Document, Transform } from '@gltf-transform/core';\nimport { getTextureColorSpace, listTextureSlots } from '@gltf-transform/functions';\nimport { KHR_DF_PRIMARIES_BT709, KHR_DF_PRIMARIES_UNSPECIFIED, read, write } from 'ktx-parse';\n\nconst NAME = 'ktxfix';\n\nexport function ktxfix(): Transform {\n\treturn async (doc: Document): Promise<void> => {\n\t\tconst logger = doc.getLogger();\n\n\t\tlet numChanged = 0;\n\n\t\tfor (const texture of doc.getRoot().listTextures()) {\n\t\t\tif (texture.getMimeType() !== 'image/ktx2') continue;\n\n\t\t\tconst image = texture.getImage();\n\t\t\tif (!image) continue;\n\n\t\t\tconst ktx = read(image);\n\t\t\tconst dfd = ktx.dataFormatDescriptor[0];\n\t\t\tconst slots = listTextureSlots(texture);\n\n\t\t\t// Don't make changes if we have no information.\n\t\t\tif (slots.length === 0) continue;\n\n\t\t\tconst colorSpace = getTextureColorSpace(texture);\n\t\t\tconst colorPrimaries = colorSpace === 'srgb' ? KHR_DF_PRIMARIES_BT709 : KHR_DF_PRIMARIES_UNSPECIFIED;\n\t\t\tconst name = texture.getURI() || texture.getName();\n\n\t\t\tlet changed = false;\n\n\t\t\t// See: https://github.com/donmccurdy/glTF-Transform/issues/218\n\t\t\tif (dfd.colorPrimaries !== colorPrimaries) {\n\t\t\t\tdfd.colorPrimaries = colorPrimaries;\n\t\t\t\tlogger.info(`${NAME}: Set colorPrimaries=${colorPrimaries} for texture \"${name}\"`);\n\t\t\t\tchanged = true;\n\t\t\t}\n\n\t\t\tif (changed) {\n\t\t\t\ttexture.setImage(write(ktx));\n\t\t\t\tnumChanged++;\n\t\t\t}\n\t\t}\n\n\t\tlogger.info(`${NAME}: Found and repaired issues in ${numChanged} textures`);\n\t\tlogger.debug(`${NAME}: Complete.`);\n\t};\n}\n","import fs from 'node:fs';\nimport {\n\ttype Buffer,\n\ttype Document,\n\tFileUtils,\n\tImageUtils,\n\ttype NodeIO,\n\tPropertyType,\n\ttype Texture,\n\ttype Transform,\n} from '@gltf-transform/core';\nimport { dedup, mergeDocuments, unpartition } from '@gltf-transform/functions';\n\nconst NAME = 'merge';\n\nexport interface MergeOptions {\n\tio: NodeIO;\n\tpaths: string[];\n\tpartition?: boolean;\n\tmergeScenes?: boolean;\n}\n\nconst merge = (options: MergeOptions): Transform => {\n\tconst { paths, io } = options;\n\n\treturn async (document: Document): Promise<void> => {\n\t\tconst root = document.getRoot();\n\t\tconst logger = document.getLogger();\n\n\t\tfor (let i = 0; i < paths.length; i++) {\n\t\t\tconst path = paths[i];\n\n\t\t\tlogger.debug(`Merging ${i + 1} / ${paths.length}, ${path}`);\n\n\t\t\tconst basename = FileUtils.basename(path);\n\t\t\tconst extension = FileUtils.extension(path).toLowerCase();\n\t\t\tif (['png', 'jpg', 'jpeg', 'webp', 'ktx2'].includes(extension)) {\n\t\t\t\tdocument\n\t\t\t\t\t.createTexture(basename)\n\t\t\t\t\t.setImage(fs.readFileSync(path))\n\t\t\t\t\t.setMimeType(ImageUtils.extensionToMimeType(extension))\n\t\t\t\t\t.setURI(basename + '.' + extension);\n\t\t\t} else if (['gltf', 'glb'].includes(extension)) {\n\t\t\t\tmergeDocuments(document, renameScenes(basename, await io.read(path)));\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Unknown file extension: \"${extension}\".`);\n\t\t\t}\n\t\t}\n\n\t\tconst rootScene = root.listScenes()[0];\n\n\t\tfor (const scene of document.getRoot().listScenes()) {\n\t\t\tif (scene === rootScene) {\n\t\t\t\troot.setDefaultScene(rootScene);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!options.mergeScenes) continue;\n\n\t\t\tfor (const child of scene.listChildren()) {\n\t\t\t\tscene.removeChild(child);\n\t\t\t\trootScene.addChild(child);\n\t\t\t}\n\n\t\t\tscene.dispose();\n\t\t}\n\n\t\t// De-duplicate textures, then ensure that all remaining textures and buffers\n\t\t// have unique URIs. See https://github.com/donmccurdy/glTF-Transform/issues/586.\n\t\tawait document.transform(dedup({ propertyTypes: [PropertyType.TEXTURE] }));\n\t\tcreateUniqueURIs(document.getRoot().listBuffers());\n\t\tcreateUniqueURIs(document.getRoot().listTextures());\n\n\t\tif (!options.partition) {\n\t\t\tawait document.transform(unpartition());\n\t\t}\n\n\t\tlogger.debug(`${NAME}: Complete.`);\n\t};\n};\n\nfunction renameScenes(name: string, document: Document): Document {\n\tconst scenes = document.getRoot().listScenes();\n\n\tfor (let i = 0; i < scenes.length; i++) {\n\t\tif (!scenes[i].getName()) {\n\t\t\tscenes[i].setName(name + (scenes.length > 1 ? ` (${i + 1}/${scenes.length})` : ''));\n\t\t}\n\t}\n\n\treturn document;\n}\n\n/** Replaces conflicting URIs to ensure all URIs are unique. */\nfunction createUniqueURIs(resources: Buffer[] | Texture[]): void {\n\tconst total = {} as Record<string, number>;\n\tconst used = {} as Record<string, boolean>;\n\n\tfor (const resource of resources) {\n\t\tconst uri = resource.getURI();\n\t\tif (!uri) continue;\n\t\tif (!total[uri]) total[uri] = 0;\n\t\ttotal[uri]++;\n\t\tused[uri] = false;\n\t}\n\n\tfor (const resource of resources) {\n\t\tlet uri = resource.getURI();\n\t\tif (!uri || total[uri] === 1) continue;\n\n\t\tconst extension = FileUtils.extension(uri);\n\t\tconst prefix = uri.replace(new RegExp(`\\\\.${extension}`), '');\n\t\tfor (let i = 2; used[uri]; i++) {\n\t\t\turi = `${prefix}_${i++}.${extension}`;\n\t\t}\n\t\tresource.setURI(uri);\n\t\tused[uri] = true;\n\t}\n}\n\nexport { merge };\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Document, ILogger, Transform } from '@gltf-transform/core';\nimport { KHRXMP, type Packet } from '@gltf-transform/extensions';\nimport prompts, { type PromptObject } from 'prompts';\nimport { XMPContext } from '../constants.js';\n\nconst DEFAULT_LANG = 'en-US';\n\nexport interface XMPOptions {\n\tpacket?: string;\n\treset?: boolean;\n}\n\nexport const XMP_DEFAULTS = {\n\tpacket: '',\n\treset: false,\n};\n\nenum Prompt {\n\tCREATOR,\n\tDESCRIPTION,\n\tLANGUAGE,\n\tTITLE,\n\tRELATED,\n\tPREFERRED_SURFACE,\n\tCREATE_DATE,\n\tRIGHTS,\n}\n\nasync function* generateQuestions(results: Record<string, unknown>): AsyncGenerator<PromptObject> {\n\tlet lang = (results['dc:language'] as string) || DEFAULT_LANG;\n\n\tyield {\n\t\ttype: 'multiselect',\n\t\tname: '_prompts',\n\t\tmessage: 'Select XMP metadata:',\n\t\tchoices: [\n\t\t\t{ value: Prompt.CREATOR, title: 'Creator' },\n\t\t\t{ value: Prompt.TITLE, title: 'Title' },\n\t\t\t{ value: Prompt.DESCRIPTION, title: 'Description' },\n\t\t\t{ value: Prompt.RELATED, title: 'Related links' },\n\t\t\t{ value: Prompt.CREATE_DATE, title: 'Date created' },\n\t\t\t{ value: Prompt.LANGUAGE, title: 'Language' },\n\t\t\t{ value: Prompt.RIGHTS, title: 'License and rights' },\n\t\t\t{ value: Prompt.PREFERRED_SURFACE, title: 'Preferred surfaces (AR)' },\n\t\t],\n\t} as PromptObject;\n\n\tconst prompts = new Set<Prompt>(results._prompts as Prompt[]);\n\n\t// Prompt for 'dc:language' first, used as the default for Language Alternative entries.\n\tif (prompts.has(Prompt.LANGUAGE)) {\n\t\tyield {\n\t\t\ttype: 'text',\n\t\t\tname: 'dc:language',\n\t\t\tmessage: 'Language?',\n\t\t\thint: ' (dc:language)',\n\t\t\tinitial: DEFAULT_LANG,\n\t\t\tvalidate: (input: string) =>\n\t\t\t\tisLanguageTag(input) ? true : 'Unsupported language tag; refer to IETF RFC 3066.',\n\t\t};\n\n\t\tlang = results['dc:language'] as string;\n\t}\n\n\tif (prompts.has(Prompt.CREATOR)) {\n\t\tyield {\n\t\t\ttype: 'text',\n\t\t\tname: 'dc:creator',\n\t\t\tmessage: 'Creator of the model?',\n\t\t\thint: ' (dc:creator)',\n\t\t\tformat: (input: string) => createList([input]),\n\t\t} as PromptObject;\n\t}\n\n\tif (prompts.has(Prompt.TITLE)) {\n\t\tyield {\n\t\t\ttype: 'text',\n\t\t\tname: 'dc:title',\n\t\t\tmessage: 'Title of the model?',\n\t\t\thint: ' (dc:title)',\n\t\t\tformat: (input: string) => createLanguageAlternative(input, lang),\n\t\t} as PromptObject;\n\t}\n\n\tif (prompts.has(Prompt.DESCRIPTION)) {\n\t\tyield {\n\t\t\ttype: 'text',\n\t\t\tname: 'dc:description',\n\t\t\tmessage: 'Description of the model?',\n\t\t\thint: ' (dc:description)',\n\t\t\tformat: (input: string) => createLanguageAlternative(input, lang),\n\t\t} as PromptObject;\n\t}\n\n\tif (prompts.has(Prompt.RELATED)) {\n\t\tyield {\n\t\t\ttype: 'list',\n\t\t\tname: 'dc:relation',\n\t\t\tmessage: 'Related links?',\n\t\t\thint: ' Comma-separated URLs. (dc:relation)',\n\t\t\tformat: (input: string[]) => createList(input),\n\t\t} as PromptObject;\n\t}\n\n\tif (prompts.has(Prompt.RIGHTS)) {\n\t\tyield {\n\t\t\ttype: 'select',\n\t\t\tname: '_rights',\n\t\t\tmessage: 'Is the model rights-managed?',\n\t\t\thint: ' (dc:rights, xmpRights:Marked, model3d:spdxLicense)',\n\t\t\tchoices: [\n\t\t\t\t// Common SPDX license identifiers applicable to creative works.\n\t\t\t\t{ value: '', title: 'Unspecified' },\n\t\t\t\t{ value: 'UNLICENSED', title: 'Restricted by copyright, trademark, or other marking' },\n\t\t\t\t{ value: 'CC0-1.0', title: 'Public domain (CC0-1.0)' },\n\t\t\t\t{ value: 'CC-BY-4.0', title: 'Creative Commons Attribution (CC-BY-4.0)' },\n\t\t\t\t{ value: 'CC-BY-ND-4.0', title: 'Creative Commons Attribution-NoDerivs (CC-BY-ND-4.0)' },\n\t\t\t\t{ value: 'CC-BY-SA-4.0', title: 'Creative Commons Attribution-ShareAlike (CC-BY-SA-4.0)' },\n\t\t\t\t{ value: 'CC-BY-NC-4.0', title: 'Creative Commons Attribution-NonCommercial (CC-BY-NC-4.0)' },\n\t\t\t\t{\n\t\t\t\t\tvalue: 'CC-BY-NC-ND-4.0',\n\t\t\t\t\ttitle: 'Creative Commons Attribution-NonCommercial-NoDerivs (CC-BY-NC-ND-4.0)',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: 'CC-BY-NC-SA-4.0',\n\t\t\t\t\ttitle: 'Creative Commons Attribution-NonCommercial-ShareAlike (CC-BY-NC-SA-4.0)',\n\t\t\t\t},\n\t\t\t\t{ value: 'OTHER', title: 'Other license' },\n\t\t\t],\n\t\t} as PromptObject;\n\n\t\tif (results._rights === 'UNLICENSED') {\n\t\t\tresults['xmpRights:Marked'] = true;\n\n\t\t\tyield {\n\t\t\t\ttype: 'text',\n\t\t\t\tname: 'xmpRights:Owner',\n\t\t\t\tmessage: 'Who is the intellectual property (IP) owner?',\n\t\t\t\thint: ' (xmpRights:Owner)',\n\t\t\t\tformat: (input: string) => createList([input]),\n\t\t\t} as PromptObject;\n\n\t\t\tyield {\n\t\t\t\ttype: 'text',\n\t\t\t\tname: '_usage',\n\t\t\t\tmessage: 'Other usage instructions?',\n\t\t\t\thint: ' Plain text or URL. (xmpRights:UsageTerms, xmpRights:WebStatement)',\n\t\t\t} as PromptObject;\n\n\t\t\tconst usage = results._usage as string;\n\t\t\tif (/^https?:\\/\\//.test(usage)) {\n\t\t\t\tresults['xmpRights:WebStatement'] = usage;\n\t\t\t} else if (usage) {\n\t\t\t\tresults['xmpRights:UsageTerms'] = createLanguageAlternative(usage, lang);\n\t\t\t}\n\t\t}\n\n\t\tif (results._rights === 'OTHER') {\n\t\t\tyield {\n\t\t\t\ttype: 'confirm',\n\t\t\t\tname: '_isLicenseSPDX',\n\t\t\t\tmessage: 'Does the license have an SPDX ID?',\n\t\t\t\thint: ' See https://spdx.dev/.',\n\t\t\t} as PromptObject;\n\n\t\t\tif (results._isLicenseSPDX) {\n\t\t\t\tyield {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tname: 'model3d:spdxLicense',\n\t\t\t\t\tmessage: 'What is the SPDX license ID?',\n\t\t\t\t\thint: ' (model3d:spdxLicense)',\n\t\t\t\t} as PromptObject;\n\t\t\t} else {\n\t\t\t\tyield {\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tname: 'dc:rights',\n\t\t\t\t\tmessage: 'What is the plain text license or rights statement?',\n\t\t\t\t\thint: ' (dc:rights)',\n\t\t\t\t\tformat: (input: string) => createLanguageAlternative(input, lang),\n\t\t\t\t} as PromptObject;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (prompts.has(Prompt.CREATE_DATE)) {\n\t\tyield {\n\t\t\ttype: 'date',\n\t\t\tname: 'xmp:CreateDate',\n\t\t\tmessage: 'Date created?',\n\t\t\thint: ' (xmp:CreateDate)',\n\t\t\tmask: 'YYYY-MM-DD',\n\t\t\tformat: (d) => d.toISOString().substring(0, 10),\n\t\t} as PromptObject;\n\t}\n\n\tif (prompts.has(Prompt.PREFERRED_SURFACE)) {\n\t\tyield {\n\t\t\ttype: 'multiselect',\n\t\t\tname: 'model3d:preferredSurfaces',\n\t\t\tmessage: 'Preferred surfaces for augmented reality (AR)? Select all that apply.',\n\t\t\thint: ' (model3d:preferredSurfaces)',\n\t\t\tchoices: [\n\t\t\t\t{\n\t\t\t\t\tvalue: 'horizontal_up',\n\t\t\t\t\ttitle: 'horizontal_up (rests on top of horizontal surfaces)',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: 'horizontal_down',\n\t\t\t\t\ttitle: 'horizontal_down (suspended from horizontal surfaces)',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: 'vertical',\n\t\t\t\t\ttitle: 'vertical (attaches to vertical surfaces)',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: 'human_face',\n\t\t\t\t\ttitle: 'human_face (worn or displayed on a human face)',\n\t\t\t\t},\n\t\t\t],\n\t\t\tformat: (input: string[]) => createList(input),\n\t\t} as PromptObject;\n\t}\n}\n\nexport const xmp = (_options: XMPOptions = XMP_DEFAULTS): Transform => {\n\tconst options = { ...XMP_DEFAULTS, ..._options } as Required<XMPOptions>;\n\n\treturn async (document: Document): Promise<void> => {\n\t\tconst logger = document.getLogger();\n\t\tconst root = document.getRoot();\n\t\tconst xmpExtension = document.createExtension(KHRXMP);\n\n\t\tif (options.reset) {\n\t\t\txmpExtension.dispose();\n\t\t\tlogger.info('[xmp]: Reset XMP metadata.');\n\t\t\tlogger.debug('[xmp]: Complete.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (options.packet) {\n\t\t\tconst packetPath = path.resolve(options.packet);\n\t\t\tlogger.info(`[xmp]: Loading \"${packetPath}\"...`);\n\t\t\tconst packetJSON = await fs.readFile(packetPath, 'utf-8');\n\t\t\tconst packetDef = validatePacket(JSON.parse(packetJSON));\n\t\t\tconst packet = xmpExtension.createPacket().fromJSONLD(packetDef);\n\t\t\troot.setExtension('KHR_xmp_json_ld', packet);\n\t\t\tlogger.debug('[xmp]: Complete.');\n\t\t\treturn;\n\t\t}\n\n\t\tconst packet = root.getExtension<Packet>('KHR_xmp_json_ld') || xmpExtension.createPacket();\n\t\tconst results = packet.toJSONLD();\n\n\t\ttry {\n\t\t\tfor await (const question of generateQuestions(results)) {\n\t\t\t\tObject.assign(results, await prompts(question));\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tcheckTTY(e, logger);\n\t\t\tthrow e;\n\t\t}\n\n\t\t// Context.\n\t\tpacket.setContext({\n\t\t\t...packet.getContext(),\n\t\t\t...createContext(results),\n\t\t\txmp: XMPContext.xmp, // required for xmp:MetadataDate below.\n\t\t});\n\n\t\t// Properties.\n\t\tlet numProperties = 0;\n\t\tfor (const name in results) {\n\t\t\t// NOTICE: Calling 'continue' in this context hits a Babel bug.\n\t\t\tif (!name.startsWith('_') && !name.startsWith('@') && results[name]) {\n\t\t\t\tpacket.setProperty(name, results[name] as string);\n\t\t\t\tnumProperties++;\n\t\t\t}\n\t\t}\n\n\t\tif (numProperties === 0) {\n\t\t\tthrow new Error('xmp: No properties added.');\n\t\t}\n\n\t\t// xmp:MetadataDate should be the same as, or more recent than, xmp:ModifyDate.\n\t\tpacket.setProperty('xmp:MetadataDate', new Date().toISOString().substring(0, 10));\n\n\t\troot.setExtension('KHR_xmp_json_ld', packet);\n\n\t\tlogger.debug(`[xmp]: Packet contents: ${JSON.stringify(packet.toJSONLD(), null, 2)}`);\n\t\tlogger.debug('[xmp]: Complete.');\n\t};\n};\n\n/** Validates a JSON-LD XMP packet for basic expectations. */\nfunction validatePacket(packetDef: Record<string, unknown>): Record<string, unknown> {\n\t// Check context.\n\tconst context = packetDef['@context'] as Record<string, unknown>;\n\tif (!context) {\n\t\tthrow new Error('Missing @context in packet.');\n\t}\n\n\t// Check properties.\n\tfor (const name in packetDef) {\n\t\tif (name.startsWith('@')) continue;\n\n\t\tconst prefix = name.split(':')[0];\n\t\tif (!prefix) {\n\t\t\tthrow new Error(`Invalid property, \"${name}\"`);\n\t\t}\n\t\tif (!(prefix in context)) {\n\t\t\tthrow new Error(`Missing context definition, \"${prefix}\"`);\n\t\t}\n\t}\n\n\treturn packetDef;\n}\n\n/**\n * The 'inquirer' library supports most terminal clients, but won't run in non-interactive\n * environments. Check errors and try to provide a useful warning to the user.\n * See: https://github.com/SBoudrias/Inquirer.js#Support.\n */\nfunction checkTTY(error: unknown, logger: ILogger) {\n\tif ((error as { isTtyError?: boolean }).isTtyError) {\n\t\tlogger.warn(\n\t\t\t'Unable to run \"inquirer\" session in this terminal environment.' +\n\t\t\t\t' Try another terminal or provide a --packet JSON-LD input.',\n\t\t);\n\t}\n}\n\n/** Creates a Language Alternative entry with a single language. */\nfunction createLanguageAlternative(value: string, language: string): Record<string, unknown> | null {\n\tif (!value) return null;\n\treturn {\n\t\t'@type': 'rdf:Alt',\n\t\t'rdf:_1': {\n\t\t\t'@language': language,\n\t\t\t'@value': value,\n\t\t},\n\t};\n}\n\n/** Creates a List entry. */\nfunction createList(list: string[]): Record<string, unknown> | null {\n\tlist = list.filter((value) => !!value);\n\tif (!list.length) return null;\n\treturn { '@list': list };\n}\n\nfunction createContext(_object: unknown, acc: Record<string, string> = {}): Record<string, string> {\n\tif (Object.prototype.toString.call(_object) !== '[object Object]') return acc;\n\n\tconst object = _object as Record<string, unknown>;\n\tfor (const key in object) {\n\t\tconst value = object[key];\n\t\tconst [prefix, suffix] = key.split(':');\n\t\tif (prefix && suffix && prefix in XMPContext) {\n\t\t\tacc[prefix] = XMPContext[prefix];\n\t\t\tcreateContext(value, acc);\n\t\t}\n\t}\n\n\treturn acc;\n}\n\n/**\n * Matches basic IANA Language Tags. Some valid tags may fail this check, but\n * the only fully-reliable alternatives I'm aware of (e.g. the 'language-tags'\n * package) are too heavy.\n *\n * Source: https://stackoverflow.com/a/48300605\n */\nconst IANA_LANGUAGE_TAG_RE = /^[A-Za-z]{2,4}([_-][A-Za-z]{4})?([_-]([A-Za-z]{2}|[0-9]{3}))?$/;\n\nfunction isLanguageTag(tag: string): boolean {\n\treturn IANA_LANGUAGE_TAG_RE.test(tag);\n}\n","import { gzip as _gzip } from 'node:zlib';\n\nexport async function gzip(src: Buffer): Promise<Buffer> {\n\treturn new Promise((resolve, reject) => {\n\t\t_gzip(src, (err, result) => {\n\t\t\tif (err) {\n\t\t\t\treject(err);\n\t\t\t} else {\n\t\t\t\tresolve(result);\n\t\t\t}\n\t\t});\n\t});\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { ILogger } from '@gltf-transform/core';\nimport { formatHeader, formatTable, TableFormat } from './utils/format.js';\nimport { log } from './utils/log.js';\n\nexport interface ValidateOptions {\n\tlimit: number;\n\tignore: string[];\n\tformat: TableFormat;\n}\n\ninterface ValidatorReport {\n\tissues: { messages: ValidatorMessage[] };\n}\n\ninterface ValidatorMessage {\n\tseverity: number;\n}\n\nconst HEADER = ['code', 'message', 'severity', 'pointer'];\n\nexport async function validate(input: string, options: ValidateOptions, logger: ILogger): Promise<void> {\n\tconst [buffer, validator] = await Promise.all([fs.readFile(input), import('gltf-validator')]);\n\treturn validator\n\t\t.validateBytes(new Uint8Array(buffer), {\n\t\t\tmaxIssues: options.limit,\n\t\t\tignoredIssues: options.ignore,\n\t\t\texternalResourceFunction: async (uri: string) => {\n\t\t\t\turi = path.resolve(path.dirname(input), decodeURIComponent(uri));\n\t\t\t\treturn fs.readFile(uri).catch((err) => {\n\t\t\t\t\tlogger.warn(`Unable to validate \"${uri}\": ${err.toString()}.`);\n\t\t\t\t\tthrow err.toString();\n\t\t\t\t});\n\t\t\t},\n\t\t})\n\t\t.then(async (report: ValidatorReport) => {\n\t\t\tif (options.format === TableFormat.CSV) {\n\t\t\t\tawait printCSV(report);\n\t\t\t} else {\n\t\t\t\tawait printTable('error', 0, report, logger, options.format);\n\t\t\t\tawait printTable('warning', 1, report, logger, options.format);\n\t\t\t\tawait printTable('info', 2, report, logger, options.format);\n\t\t\t\tawait printTable('hint', 3, report, logger, options.format);\n\t\t\t}\n\t\t\treturn report;\n\t\t})\n\t\t.then((report: ValidatorReport) => {\n\t\t\tif (report.issues.messages.some((message) => message.severity === 0)) {\n\t\t\t\tthrow new Error('Validation detected errors.');\n\t\t\t}\n\t\t});\n}\n\nasync function printCSV(report: ValidatorReport): Promise<void> {\n\tconst messages = report.issues.messages;\n\tconsole.log(await formatTable(TableFormat.CSV, HEADER, messages.map(Object.values)));\n\treturn;\n}\n\nasync function printTable(\n\theader: string,\n\tseverity: number,\n\treport: ValidatorReport,\n\tlogger: ILogger,\n\tformat: TableFormat,\n): Promise<void> {\n\tlog(formatHeader(header));\n\tconst messages = report.issues.messages.filter((msg) => msg.severity === severity);\n\tif (messages.length) {\n\t\tlog(await formatTable(format, HEADER, messages.map(Object.values)));\n\t} else {\n\t\tlogger.info(`No ${header}s found.`);\n\t}\n\tlog('\\n');\n}\n","import { readFile, writeFile } from 'node:fs/promises';\nimport { styleText } from 'node:util';\nimport { type Logger, NodeIO, PropertyType, type Transform, VertexLayout, type vec2 } from '@gltf-transform/core';\nimport {\n\ttype CenterOptions,\n\tcenter,\n\tDRACO_DEFAULTS,\n\ttype DracoOptions,\n\tdedup,\n\tdequantize,\n\tdraco,\n\ttype FlattenOptions,\n\tflatten,\n\tINSTANCE_DEFAULTS,\n\ttype InstanceOptions,\n\tinstance,\n\tJOIN_DEFAULTS,\n\ttype JoinOptions,\n\tjoin,\n\tMESHOPT_DEFAULTS,\n\tmeshopt,\n\tmetalRough,\n\tPALETTE_DEFAULTS,\n\ttype PaletteOptions,\n\ttype PartitionOptions,\n\tPRUNE_DEFAULTS,\n\ttype PruneOptions,\n\tpalette,\n\tpartition,\n\tprune,\n\tQUANTIZE_DEFAULTS,\n\tquantize,\n\ttype ResampleOptions,\n\treorder,\n\tresample,\n\ttype SequenceOptions,\n\tSIMPLIFY_DEFAULTS,\n\ttype SparseOptions,\n\tsequence,\n\tsimplify,\n\tsparse,\n\tTEXTURE_COMPRESS_SUPPORTED_FORMATS,\n\tTextureResizeFilter,\n\ttangents,\n\ttextureCompress,\n\tUNWRAP_DEFAULTS,\n\ttype UnweldOptions,\n\tunlit,\n\tunweld,\n\tunwrap,\n\ttype WeldOptions,\n\tweld,\n} from '@gltf-transform/functions';\nimport { ready as resampleReady, resample as resampleWASM } from 'keyframe-resample';\nimport { MeshoptEncoder, MeshoptSimplifier } from 'meshoptimizer';\nimport micromatch from 'micromatch';\nimport mikktspace from 'mikktspace';\nimport * as watlas from 'watlas';\nimport { getConfig, loadConfig } from './config.js';\nimport { inspect } from './inspect.js';\nimport { program, Validator } from './program.js';\nimport { Session } from './session.js';\nimport {\n\tETC1S_DEFAULTS,\n\tFilter,\n\tktxdecompress,\n\tktxfix,\n\tMode,\n\tmerge,\n\ttoktx,\n\tUASTC_DEFAULTS,\n\ttype XMPOptions,\n\txmp,\n} from './transforms/index.js';\nimport { formatBytes, TableFormat } from './utils/format.js';\nimport { gzip } from './utils/gzip.js';\nimport { MICROMATCH_OPTIONS, regexFromArray } from './utils/match.js';\nimport { type ValidateOptions, validate } from './validate.js';\n\nlet io: NodeIO;\n\nconst programReady: Promise<void> = new Promise<void>((resolve) => {\n\t// Manually detect and handle --config, before program actually runs.\n\tif (process.argv.includes('--config')) {\n\t\tloadConfig(process.argv[process.argv.indexOf('--config') + 1]);\n\t}\n\treturn getConfig().then(async (config) => {\n\t\tio = new NodeIO(global.fetch).registerExtensions(config.extensions).registerDependencies(config.dependencies);\n\t\tif (config.onProgramReady) {\n\t\t\tprogram.section('User', '👤');\n\t\t\tawait config.onProgramReady({ program, io, Session });\n\t\t}\n\t\tresolve();\n\t});\n});\n\nconst INPUT_DESC = 'Path to read glTF 2.0 (.glb, .gltf) model';\nconst OUTPUT_DESC = 'Path to write output';\n\nprogram\n\t.version(import.meta.env.PACKAGE_VERSION)\n\t.description('Command-line interface (CLI) for the glTF Transform SDK.');\n\nif (process.argv && !process.argv.includes('--no-editorial')) {\n\tprogram.help(\n\t\t`\nTo run the most common optimizations in one easy step, use the 'optimize' command:\n\n▸ gltf-transform optimize <input> <output> --compress draco --texture-compress webp\n\nDefaults in the 'optimize' command may not be ideal for all scenes. Some of its\nfeatures can be configured (${styleText('dim', `optimize --help`)}), or more advanced users may wish\nto inspect their scenes then pick and choose optimizations.\n\n▸ gltf-transform inspect <input>\n\nThe report printed by the 'inspect' command should identify performance issues,\nand whether the scene is generally geometry-heavy, texture-heavy, has too many\ndraw calls, etc. Apply individual commands below to deal with any of these\nissues as needed.\n`.trim(),\n\t);\n}\n\nprogram.section('Inspect', '🔎');\n\n// INSPECT\nprogram\n\t.command('inspect', 'Inspect contents of the model')\n\t.help(\n\t\t`\nInspect the contents of the model, printing a table with properties and\nstatistics for scenes, meshes, materials, textures, and animations contained\nby the file. This data is useful for understanding how much of a file's size\nis comprised of geometry vs. textures, which extensions are needed when loading\nthe file, and which material properties are being used.\n\nUse --format=csv or --format=md for alternative display formats.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.option('--format <format>', 'Table output format', {\n\t\tvalidator: [TableFormat.PRETTY, TableFormat.CSV, TableFormat.MD],\n\t\tdefault: TableFormat.PRETTY,\n\t})\n\t.action(async ({ args, options, logger }) => {\n\t\tio.setLogger(logger as unknown as Logger);\n\t\tawait inspect(\n\t\t\tawait io.readAsJSON(args.input as string),\n\t\t\tio,\n\t\t\tlogger as unknown as Logger,\n\t\t\toptions.format as TableFormat,\n\t\t);\n\t});\n\n// VALIDATE\nprogram\n\t.command('validate', 'Validate model against the glTF spec')\n\t.help(\n\t\t`\nValidate the model with official glTF validator. The validator detects whether\na file conforms correctly to the glTF specification, and is useful for\ndebugging issues with a model. Validation errors typically suggest a problem\nin the authoring process, and can be reported as bugs on the software used to\nexport the file. Certain lower-priority issues are not technically invalid, but\nmay indicate an unintended situation in the file, like unused data not attached\nto any particular scene.\n\nFor more details about the official validation suite used here, see:\nhttps://github.com/KhronosGroup/glTF-Validator\n\nExample:\n\n  ▸ gltf-transform validate input.glb --ignore ACCESSOR_WEIGHTS_NON_NORMALIZED\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.option('--limit <limit>', 'Limit number of issues to display', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: 1e7,\n\t})\n\t.option('--ignore <CODE>,<CODE>,...', 'Issue codes to be ignored', {\n\t\tvalidator: Validator.ARRAY,\n\t\tdefault: [],\n\t})\n\t.option('--format <format>', 'Table output format', {\n\t\tvalidator: [TableFormat.PRETTY, TableFormat.CSV, TableFormat.MD],\n\t\tdefault: TableFormat.PRETTY,\n\t})\n\t.action(({ args, options, logger }) => {\n\t\treturn validate(args.input as string, options as unknown as ValidateOptions, logger as unknown as Logger);\n\t});\n\nprogram.section('Package', '📦');\n\n// COPY\nprogram\n\t.command('copy', 'Copy model with minimal changes')\n\t.alias('cp')\n\t.help(\n\t\t`\nCopy the model from <input> to <output> with minimal changes. Unlike filesystem\n\\`cp\\`, this command does parse the file into glTF Transform's internal\nrepresentation before serializing it to disk again. No other intentional\nchanges are made, so copying a model can be a useful first step to confirm that\nglTF Transform is reading and writing the model correctly when debugging issues\nin a larger script doing more complex processing of the file. Copying may also\nbe used to ensure consistent data layout across glTF files from different\nexporters, e.g. if your engine always requires interleaved vertex attributes.\n\nWhile vertex data remains byte-for-byte the same before and after copying, and\nscene, node, material, and other properties are also preserved losslessly,\ncertain aspects of data layout may change slightly with this process:\n\n- Vertex attributes within a mesh are interleaved.\n- Accessors are organized into buffer views according to usage.\n- Draco compression is removed to avoid a lossy decompress/compress round trip.\n`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, logger }) => Session.create(io, logger, args.input, args.output).transform());\n\n// OPTIMIZE\nprogram\n\t.command('optimize', 'Optimize model by all available methods')\n\t.help(\n\t\t`\nOptimize the model by all available methods. Combines many features of the\nglTF Transform CLI into a single command for convenience and faster results.\nFor more control over the optimization process, consider running individual\ncommands or using the scripting API.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--instance <bool>', 'Use GPU instancing with shared mesh references.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--instance-min <min>', 'Number of instances required for instancing.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: INSTANCE_DEFAULTS.min,\n\t})\n\t.option('--meshopt-level <level>', 'Meshopt compression level.', {\n\t\tvalidator: ['medium', 'high'],\n\t\tdefault: 'high',\n\t})\n\t.option('--palette <bool>', 'Creates palette textures and merges materials.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option(\n\t\t'--palette-min <min>',\n\t\t'Minimum number of blocks in the palette texture. If fewer unique ' +\n\t\t\t'material values are found, no palettes will be generated.',\n\t\t{\n\t\t\tvalidator: Validator.NUMBER,\n\t\t\tdefault: PALETTE_DEFAULTS.min,\n\t\t},\n\t)\n\t.option('--simplify <bool>', 'Simplify mesh geometry with meshoptimizer.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--simplify-error <error>', 'Simplification error tolerance, as a fraction of mesh extent.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: SIMPLIFY_DEFAULTS.error,\n\t})\n\t.option('--simplify-ratio <ratio>', 'Target ratio (0–1) of vertices to keep.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: SIMPLIFY_DEFAULTS.ratio,\n\t})\n\t.option('--simplify-lock-border <bool>', 'Whether to lock topological borders of the mesh.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: SIMPLIFY_DEFAULTS.lockBorder,\n\t})\n\t.option('--prune <bool>', 'Removes properties from the file if they are not referenced by a Scene.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--prune-attributes <bool>', 'Whether to prune unused vertex attributes.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option(\n\t\t'--prune-solid-textures <bool>',\n\t\t'Whether to prune solid (single-color) textures, converting them to material factors.',\n\t\t{\n\t\t\tvalidator: Validator.BOOLEAN,\n\t\t\tdefault: true,\n\t\t},\n\t)\n\t.option(\n\t\t'--sparse <bool>',\n\t\t'Reduces storage for zero-filled arrays. If disabled, existing accessors (sparse or not) ' +\n\t\t\t'are left unchanged.',\n\t\t{\n\t\t\tvalidator: Validator.BOOLEAN,\n\t\t\tdefault: true,\n\t\t},\n\t)\n\t.option(\n\t\t'--compress <method>',\n\t\t'Floating point compression method. Draco compresses geometry; Meshopt ' +\n\t\t\t'and quantization compress geometry and animation.',\n\t\t{\n\t\t\tvalidator: ['draco', 'meshopt', 'quantize', false],\n\t\t\tdefault: 'meshopt',\n\t\t},\n\t)\n\t.option(\n\t\t'--texture-compress <format>',\n\t\t'Texture compression format. KTX2 optimizes VRAM usage and performance; ' +\n\t\t\t'AVIF and WebP optimize transmission size. Auto recompresses in original format.',\n\t\t{\n\t\t\tvalidator: ['ktx2', 'webp', 'avif', 'auto', false],\n\t\t\tdefault: 'auto',\n\t\t},\n\t)\n\t.option('--texture-size <size>', 'Maximum texture dimensions, in pixels.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: 2048,\n\t})\n\t.option('--flatten <bool>', 'Flatten scene graph.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--join <bool>', 'Join meshes and reduce draw calls. Requires `--flatten`.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--join-meshes <bool>', 'Join distinct meshes and nodes. Requires `--join`.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: !JOIN_DEFAULTS.keepMeshes,\n\t})\n\t.option('--join-named <bool>', 'Join named meshes and nodes. Requires `--join`.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: !JOIN_DEFAULTS.keepNamed,\n\t})\n\t.option('--weld <bool>', 'Merge equivalent vertices. Required when simplifying geometry.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--resample <bool>', 'Resample animations, losslessly deduplicating keyframes', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.action(async ({ args, options, logger }) => {\n\t\tconst opts = options as {\n\t\t\tinstance: boolean;\n\t\t\tinstanceMin: number;\n\t\t\tmeshoptLevel: 'medium' | 'high';\n\t\t\tpalette: boolean;\n\t\t\tpaletteMin: number;\n\t\t\tsimplify: boolean;\n\t\t\tsimplifyError: number;\n\t\t\tsimplifyRatio: number;\n\t\t\tsimplifyLockBorder: boolean;\n\t\t\tprune: boolean;\n\t\t\tpruneAttributes: boolean;\n\t\t\tpruneSolidTextures: boolean;\n\t\t\tsparse: boolean;\n\t\t\tcompress: 'draco' | 'meshopt' | 'quantize' | false;\n\t\t\ttextureCompress: 'ktx2' | 'webp' | 'webp' | 'auto' | false;\n\t\t\ttextureSize: number;\n\t\t\tflatten: boolean;\n\t\t\tresample: boolean;\n\t\t\tjoin: boolean;\n\t\t\tjoinNamed: boolean;\n\t\t\tjoinMeshes: boolean;\n\t\t\tweld: boolean;\n\t\t};\n\n\t\t// Baseline transforms.\n\t\tconst transforms: Transform[] = [dedup()];\n\n\t\tif (opts.instance) transforms.push(instance({ min: opts.instanceMin }));\n\n\t\tif (opts.palette) {\n\t\t\ttransforms.push(palette({ min: opts.paletteMin }));\n\t\t}\n\n\t\tif (opts.flatten) transforms.push(flatten());\n\t\tif (opts.join) {\n\t\t\ttransforms.push(\n\t\t\t\tjoin({\n\t\t\t\t\tkeepNamed: !opts.joinNamed,\n\t\t\t\t\tkeepMeshes: !opts.joinMeshes,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tif (opts.weld) transforms.push(weld());\n\n\t\tif (opts.simplify) {\n\t\t\ttransforms.push(\n\t\t\t\tsimplify({\n\t\t\t\t\tsimplifier: MeshoptSimplifier,\n\t\t\t\t\terror: opts.simplifyError,\n\t\t\t\t\tratio: opts.simplifyRatio,\n\t\t\t\t\tlockBorder: opts.simplifyLockBorder,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (opts.resample) transforms.push(resample({ ready: resampleReady, resample: resampleWASM }));\n\n\t\tif (opts.prune) {\n\t\t\ttransforms.push(\n\t\t\t\tprune({\n\t\t\t\t\tkeepAttributes: !opts.pruneAttributes,\n\t\t\t\t\tkeepIndices: false,\n\t\t\t\t\tkeepLeaves: false,\n\t\t\t\t\tkeepSolidTextures: !opts.pruneSolidTextures,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\tif (opts.sparse) transforms.push(sparse());\n\n\t\t// Texture compression.\n\t\tif (opts.textureCompress === 'ktx2') {\n\t\t\tconst { default: encoder } = await import('sharp');\n\t\t\tconst slotsUASTC = micromatch.makeRe(\n\t\t\t\t'{normalTexture,occlusionTexture,metallicRoughnessTexture}',\n\t\t\t\tMICROMATCH_OPTIONS,\n\t\t\t);\n\t\t\ttransforms.push(\n\t\t\t\ttoktx({\n\t\t\t\t\tencoder,\n\t\t\t\t\tresize: [opts.textureSize, opts.textureSize],\n\t\t\t\t\tmode: Mode.UASTC,\n\t\t\t\t\tslots: slotsUASTC,\n\t\t\t\t\tlevel: 4,\n\t\t\t\t\trdo: true,\n\t\t\t\t\trdoLambda: 4,\n\t\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t\t}),\n\t\t\t\ttoktx({\n\t\t\t\t\tencoder,\n\t\t\t\t\tresize: [opts.textureSize, opts.textureSize],\n\t\t\t\t\tmode: Mode.ETC1S,\n\t\t\t\t\tquality: 255,\n\t\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t\t}),\n\t\t\t);\n\t\t} else if (opts.textureCompress !== false) {\n\t\t\tconst { default: encoder } = await import('sharp');\n\t\t\ttransforms.push(\n\t\t\t\ttextureCompress({\n\t\t\t\t\tencoder,\n\t\t\t\t\tresize: [opts.textureSize, opts.textureSize],\n\t\t\t\t\ttargetFormat: opts.textureCompress === 'auto' ? undefined : opts.textureCompress,\n\t\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\n\t\t// Mesh compression last. Doesn't matter here, but in one-off CLI\n\t\t// commands we want to avoid recompressing mesh data.\n\t\tif (opts.compress === 'draco') {\n\t\t\tif (opts.weld === false) {\n\t\t\t\tlogger.warn('Ignoring --no-weld, required for Draco compression.');\n\t\t\t}\n\t\t\ttransforms.push(draco());\n\t\t} else if (opts.compress === 'meshopt') {\n\t\t\ttransforms.push(meshopt({ encoder: MeshoptEncoder, level: opts.meshoptLevel }));\n\t\t} else if (opts.compress === 'quantize') {\n\t\t\ttransforms.push(quantize());\n\t\t}\n\n\t\treturn Session.create(io, logger, args.input, args.output)\n\t\t\t.setDisplay(true)\n\t\t\t.transform(...transforms);\n\t});\n\n// MERGE\nprogram\n\t.command('merge', 'Merge two or more models into one')\n\t.help(\n\t\t`\nMerge two or more models into one, each in a separate Scene. Optionally, the\nbinary data for each model may be kept in a separate buffer with the\n--partition flag.\n\nExample:\n\n  ▸ gltf-transform merge a.glb b.glb c.glb output.glb\n\t`.trim(),\n\t)\n\t.argument('<path...>', `${INPUT_DESC}(s). Final path is used to write output.`)\n\t.option('--partition', 'Whether to keep separate buffers for each input file. Invalid for GLB output.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.option('--merge-scenes', 'Whether to merge scenes, or keep one scene per input file.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.action(({ args, options, logger }) => {\n\t\tconst paths = typeof args.path === 'string' ? args.path.split(',') : (args.path as string[]);\n\t\tconst output = paths.pop();\n\t\treturn Session.create(io, logger, '', output).transform(merge({ io, paths, ...options }));\n\t});\n\n// PARTITION\nprogram\n\t.command('partition', 'Partition binary data into separate .bin files')\n\t.help(\n\t\t`\nPartition binary data for meshes or animations into separate .bin files. In\nengines that support lazy-loading resources within glTF files, this allows\nrestructuring the data to minimize initial load time, fetching additional\nresources as needed. Partitioning is supported only for .gltf, not .glb, files.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--animations', 'Partition each animation into a separate .bin file', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.option('--meshes', 'Partition each mesh into a separate .bin file', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(partition(options as PartitionOptions)),\n\t);\n\n// DEDUP\nprogram\n\t.command('dedup', 'Deduplicate accessors and textures')\n\t.help(\n\t\t`\nDeduplicate accessors, textures, materials, meshes, and skins. Some exporters or\npipeline processing may lead to multiple resources within a file containing\nredundant copies of the same information. This functions scans for these cases\nand merges the duplicates where possible, reducing file size. The process may\nbe very slow on large files with many accessors.\n\nDeduplication early in a pipeline may also help other optimizations, like\ncompression and instancing, to be more effective.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--accessors <accessors>', 'Remove duplicate accessors', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--materials <materials>', 'Remove duplicate materials', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--meshes <meshes>', 'Remove duplicate meshes', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--skins <skins>', 'Remove duplicate skins', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.option('--textures <textures>', 'Remove duplicate textures', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.action(({ args, options, logger }) => {\n\t\tconst propertyTypes: string[] = [];\n\t\tif (options.accessors) propertyTypes.push(PropertyType.ACCESSOR);\n\t\tif (options.materials) propertyTypes.push(PropertyType.MATERIAL);\n\t\tif (options.meshes) propertyTypes.push(PropertyType.MESH);\n\t\tif (options.skins) propertyTypes.push(PropertyType.SKIN);\n\t\tif (options.textures) propertyTypes.push(PropertyType.TEXTURE);\n\t\treturn Session.create(io, logger, args.input, args.output).transform(dedup({ propertyTypes }));\n\t});\n\n// PRUNE\nprogram\n\t.command('prune', 'Remove unreferenced properties from the file')\n\t.help(\n\t\t`\nRemoves properties from the file if they are not referenced by a Scene. Helpful\nwhen cleaning up after complex workflows or a faulty exporter. This function\nmay (conservatively) fail to identify some unused extension properties, such as\nlights, but it will not remove anything that is still in use, even if used by\nan extension. Animations are considered unused if they do not target any nodes\nthat are children of a scene.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--keep-attributes <keepAttributes>', 'Whether to keep unused vertex attributes', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: PRUNE_DEFAULTS.keepAttributes,\n\t})\n\t.option('--keep-indices <keepIndices>', 'Whether to keep unused mesh indices', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: PRUNE_DEFAULTS.keepIndices,\n\t})\n\t.option('--keep-leaves <keepLeaves>', 'Whether to keep empty leaf nodes', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: PRUNE_DEFAULTS.keepLeaves,\n\t})\n\t.option(\n\t\t'--keep-solid-textures <keepSolidTextures>',\n\t\t'Whether to keep solid (single-color) textures, or convert to material factors',\n\t\t{\n\t\t\tvalidator: Validator.BOOLEAN,\n\t\t\tdefault: PRUNE_DEFAULTS.keepSolidTextures,\n\t\t},\n\t)\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(prune(options as unknown as PruneOptions)),\n\t);\n\n// GZIP\nprogram\n\t.command('gzip', 'Compress model with lossless gzip')\n\t.help(\n\t\t`\nCompress the model with gzip. Gzip is a general-purpose file compression\ntechnique, not specific to glTF models. On the web, decompression is\nhandled automatically by the web browser, without any intervention from the\nclient application.\n\nWhen the model contains resources that are already effectively compressed, like\nJPEG textures or Draco geometry, gzip is unlikely to add much further benefit\nand can be skipped. Other compression strategies, like Meshopt and quantization,\nwork best when combined with gzip.\n`,\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.action(async ({ args, logger }) => {\n\t\tconst inBuffer = await readFile(args.input as string);\n\t\tconst outBuffer = await gzip(inBuffer);\n\t\tconst fileName = args.input + '.gz';\n\t\tconst inSize = formatBytes(inBuffer.byteLength);\n\t\tconst outSize = formatBytes(outBuffer.byteLength);\n\t\tawait writeFile(fileName, outBuffer);\n\t\tlogger.info(`Created ${fileName} (${inSize} → ${outSize})`);\n\t});\n\n// XMP\nprogram\n\t.command('xmp', 'Add or modify XMP metadata')\n\t.help(\n\t\t`\nXMP metadata provides standardized fields describing the content, provenance, usage restrictions,\nor other attributes of a 3D model. Such metadata does not generally affect the parsing or runtime\nbehavior of the content — for that, use custom extensions, custom vertex attributes, or extras.\n\nThe easiest (and default) mode of the CLI 'xmp' command provides interactive prompts, walking\nthrough a series of questions and then constructing appropriate JSONLD output. These interactive\nprompts do not include all possible XMP namespaces and fields, but should cover most common cases.\n\nFor more advanced cases, provide an external .jsonld or .json file specified by the --packet\nflag, or use the scripting API to manually input JSONLD fields.\n\nTo remove XMP metadata and the KHR_xmp_json_ld extension, use the --reset flag.\n\n${styleText('underline', 'Documentation')}\n- https://gltf-transform.dev/classes/extensions.xmp.html\n`,\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--packet <path>', 'Path to XMP packet (.jsonld or .json)')\n\t.option('--reset', 'Reset metadata and remove XMP extension', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.action(async ({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(xmp({ ...options } as XMPOptions)),\n\t);\n\nprogram.section('Scene', '🌍');\n\n// CENTER\nprogram\n\t.command('center', 'Center the scene at the origin, or above/below it')\n\t.help(\n\t\t`\nCenter the scene at the origin, or above/below it. When loading a model into\na larger scene, or into an augmented reality context, it's often best to ensure\nthe model's pivot is centered beneath the object. For objects meant to be\nattached a surface, like a ceiling fan, the pivot may be located above instead.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pivot <pivot>', 'Method used to determine the scene pivot', {\n\t\tvalidator: ['center', 'above', 'below'],\n\t\tdefault: 'center',\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(center({ ...options } as CenterOptions)),\n\t);\n\n// INSTANCE\nprogram\n\t.command('instance', 'Create GPU instances from shared mesh references')\n\t.help(\n\t\t`\nFor meshes reused by more than one node in a scene, this command creates an\nEXT_mesh_gpu_instancing extension to aid with GPU instancing. In engines that\nsupport the extension, this may allow GPU instancing to be used, reducing draw\ncalls and improving framerate.\n\nEngines may use GPU instancing with or without the presence of this extension,\nand are strongly encouraged to do so. However, particularly when loading a\nmodel at runtime, the extension provides useful context allowing the engine to\nuse this technique efficiently.\n\nInstanced meshes cannot be animated, and must share the same materials. For\nfurther details, see:\n\nhttps://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option(\n\t\t'--min <count>',\n\t\t'Minimum number of meshes in a batch. If fewer compatible meshes ' +\n\t\t\t'are found, no instanced batches will be generated.',\n\t\t{\n\t\t\tvalidator: Validator.NUMBER,\n\t\t\tdefault: INSTANCE_DEFAULTS.min,\n\t\t},\n\t)\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(instance({ ...options } as InstanceOptions)),\n\t);\n\n// FLATTEN\nprogram\n\t.command('flatten', 'Flatten scene graph')\n\t.help(\n\t\t`\nFlattens the scene graph, leaving Nodes with Meshes, Cameras, and other\nattachments as direct children of the Scene. Skeletons and their\ndescendants are left in their original Node structure.\n\nAnimation targeting a Node or its parents will prevent that Node from being\nmoved.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(flatten({ ...options } as FlattenOptions)),\n\t);\n\n// JOIN\nprogram\n\t.command('join', 'Join meshes and reduce draw calls')\n\t.help(\n\t\t`\nJoins compatible Primitives and reduces draw calls. Primitives are eligible for\njoining if they are members of the same Mesh or, optionally, attached to sibling\nNodes in the scene hierarchy. Implicitly runs \\`dedup\\` and \\`flatten\\` commands\nfirst, to maximize the number of Primitives that can be joined.\n\nNOTE: In a Scene that heavily reuses the same Mesh data, joining may increase\nvertex count. Consider alternatives, like \\`instance\\` with\nEXT_mesh_gpu_instancing.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--keepMeshes <bool>', 'Prevents joining distinct meshes and nodes.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: JOIN_DEFAULTS.keepMeshes,\n\t})\n\t.option('--keepNamed <bool>', 'Prevents joining named meshes and nodes.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: JOIN_DEFAULTS.keepNamed,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(\n\t\t\tdedup({ propertyTypes: [PropertyType.MATERIAL] }),\n\t\t\tflatten(),\n\t\t\tjoin({ ...options } as unknown as JoinOptions),\n\t\t),\n\t);\n\nprogram.section('Geometry', '🫖');\n\n// DRACO\nprogram\n\t.command('draco', 'Compress geometry with Draco')\n\t.help(\n\t\t`\nCompress mesh geometry with the Draco library. This type of compression affects\nonly geometry data — animation and textures are not compressed.\n\nCompresses\n- geometry (only triangle meshes)\n\n${styleText('underline', 'Documentation')}\n- https://gltf-transform.dev/classes/extensions.dracomeshcompression.html\n\n${styleText('underline', 'References')}\n- draco: https://github.com/google/draco\n- KHR_draco_mesh_compression: https://github.com/KhronosGroup/gltf/blob/main/extensions/2.0/Khronos/KHR_draco_mesh_compression/\n`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--method <method>', 'Compression method.', {\n\t\tvalidator: ['edgebreaker', 'sequential'],\n\t\tdefault: 'edgebreaker',\n\t})\n\t.option('--encode-speed <encodeSpeed>', 'Encoding speed vs. compression level, 0–10.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.encodeSpeed,\n\t})\n\t.option('--decode-speed <decodeSpeed>', 'Decoding speed vs. compression level, 0–10.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.decodeSpeed,\n\t})\n\t.option('--quantize-position <bits>', 'Quantization bits for POSITION, 1-16.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.quantizePosition,\n\t})\n\t.option('--quantize-normal <bits>', 'Quantization bits for NORMAL, 1-16.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.quantizeNormal,\n\t})\n\t.option('--quantize-color <bits>', 'Quantization bits for COLOR_*, 1-16.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.quantizeColor,\n\t})\n\t.option('--quantize-texcoord <bits>', 'Quantization bits for TEXCOORD_*, 1-16.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.quantizeTexcoord,\n\t})\n\t.option('--quantize-generic <bits>', 'Quantization bits for other attributes, 1-16.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: DRACO_DEFAULTS.quantizeGeneric,\n\t})\n\t.option('--quantization-volume <volume>', 'Bounds for quantization grid.', {\n\t\tvalidator: ['mesh', 'scene'],\n\t\tdefault: DRACO_DEFAULTS.quantizationVolume,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(draco(options as unknown as DracoOptions)),\n\t);\n\n// MESHOPT\nprogram\n\t.command('meshopt', 'Compress geometry and animation with Meshopt')\n\t.help(\n\t\t`\nCompress geometry, morph targets, and animation with Meshopt. Meshopt\ncompression decodes very quickly, and is best used in combination with a\nlossless compression method like brotli or gzip.\n\nCompresses\n- geometry (points, lines, triangle meshes)\n- morph targets\n- animation tracks\n\n${styleText('underline', 'Documentation')}\n- https://gltf-transform.dev/classes/extensions.meshoptcompression.html\n\n${styleText('underline', 'References')}\n- meshoptimizer: https://github.com/zeux/meshoptimizer\n- EXT_meshopt_compression: https://github.com/KhronosGroup/gltf/blob/main/extensions/2.0/Vendor/EXT_meshopt_compression/\n`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--level <level>', 'Compression level.', {\n\t\tvalidator: ['medium', 'high'],\n\t\tdefault: 'high',\n\t})\n\t.option('--quantize-position <bits>', 'Precision for POSITION attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: MESHOPT_DEFAULTS.quantizePosition,\n\t})\n\t.option('--quantize-normal <bits>', 'Precision for NORMAL and TANGENT attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: MESHOPT_DEFAULTS.quantizeNormal,\n\t})\n\t.option('--quantize-texcoord <bits>', 'Precision for TEXCOORD_* attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: MESHOPT_DEFAULTS.quantizeTexcoord,\n\t})\n\t.option('--quantize-color <bits>', 'Precision for COLOR_* attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: MESHOPT_DEFAULTS.quantizeColor,\n\t})\n\t.option('--quantize-weight <bits>', 'Precision for WEIGHTS_* attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: MESHOPT_DEFAULTS.quantizeWeight,\n\t})\n\t.option('--quantize-generic <bits>', 'Precision for custom (_*) attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: MESHOPT_DEFAULTS.quantizeGeneric,\n\t})\n\t.option('--quantization-volume <volume>', 'Bounds for quantization grid.', {\n\t\tvalidator: ['mesh', 'scene'],\n\t\tdefault: QUANTIZE_DEFAULTS.quantizationVolume,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(meshopt({ encoder: MeshoptEncoder, ...options })),\n\t);\n\n// QUANTIZE\nprogram\n\t.command('quantize', 'Quantize geometry, reducing precision and memory')\n\t.help(\n\t\t`\nQuantization is a simple type of compression taking 32-bit float vertex\nattributes and storing them as 16-bit or 8-bit integers. A quantization factor\nrestoring the original value (with some error) is applied on the GPU, although\nnode scales and positions may also be changed to account for the quantization.\n\nQuantized vertex attributes require less space, both on disk and on the GPU.\nMost vertex attribute types can be quantized from 8–16 bits, but are always\nstored in 8- or 16-bit accessors. While a value quantized to 12 bits still\noccupies 16 bits on disk, gzip (or other lossless compression) will be more\neffective on values quantized to lower bit depths. As a result, the default\nbit depths used by this command are generally between 8 and 16 bits.\n\nBit depths for indices and JOINTS_* are determined automatically.\n\nRequires KHR_mesh_quantization support.`.trim(),\n\t)\n\t.argument('<input>', 'Path to read glTF 2.0 (.glb, .gltf) input')\n\t.argument('<output>', 'Path to write output')\n\t.option('--pattern <pattern>', 'Pattern for vertex attributes (case-insensitive glob)', {\n\t\tvalidator: Validator.STRING,\n\t\tdefault: '*',\n\t})\n\t.option('--quantize-position <bits>', 'Precision for POSITION attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: QUANTIZE_DEFAULTS.quantizePosition,\n\t})\n\t.option('--quantize-normal <bits>', 'Precision for NORMAL and TANGENT attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: QUANTIZE_DEFAULTS.quantizeNormal,\n\t})\n\t.option('--quantize-texcoord <bits>', 'Precision for TEXCOORD_* attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: QUANTIZE_DEFAULTS.quantizeTexcoord,\n\t})\n\t.option('--quantize-color <bits>', 'Precision for COLOR_* attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: QUANTIZE_DEFAULTS.quantizeColor,\n\t})\n\t.option('--quantize-weight <bits>', 'Precision for WEIGHTS_* attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: QUANTIZE_DEFAULTS.quantizeWeight,\n\t})\n\t.option('--quantize-generic <bits>', 'Precision for custom (_*) attributes.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: QUANTIZE_DEFAULTS.quantizeGeneric,\n\t})\n\t.option('--quantization-volume <volume>', 'Bounds for quantization grid.', {\n\t\tvalidator: ['mesh', 'scene'],\n\t\tdefault: QUANTIZE_DEFAULTS.quantizationVolume,\n\t})\n\t.action(({ args, options, logger }) => {\n\t\tconst pattern = micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS);\n\t\treturn Session.create(io, logger, args.input, args.output).transform(quantize({ ...options, pattern }));\n\t});\n\n// DEQUANTIZE\nprogram\n\t.command('dequantize', 'Dequantize geometry')\n\t.help(\n\t\t`\nRemoves quantization from an asset. This will increase the size of the asset on\ndisk and in memory, but may be necessary for applications that don't support\nquantization.\n\nRemoves KHR_mesh_quantization, if present.`.trim(),\n\t)\n\t.argument('<input>', 'Path to read glTF 2.0 (.glb, .gltf) input')\n\t.argument('<output>', 'Path to write output')\n\t.option('--pattern <pattern>', 'Pattern for vertex attributes (case-insensitive glob)', {\n\t\tvalidator: Validator.STRING,\n\t\tdefault: '!JOINTS_*',\n\t})\n\t.action(({ args, options, logger }) => {\n\t\tconst pattern = micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS);\n\t\treturn Session.create(io, logger, args.input, args.output).transform(dequantize({ ...options, pattern }));\n\t});\n\n// WELD\nprogram\n\t.command('weld', 'Merge equivalent vertices to optimize geometry')\n\t.help(\n\t\t`\nWelds mesh geometry, merging bitwise identical vertices. When merged and\nindexed, data is shared more efficiently between vertices. File size\ncan be reduced, and the GPU uses the vertex cache more efficiently.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(weld(options as unknown as WeldOptions)),\n\t);\n\n// UNWELD\nprogram\n\t.command('unweld', 'De-index geometry, disconnecting any shared vertices')\n\t.help(\n\t\t`\nDe-index geometry, disconnecting any shared vertices. This tends to increase\nthe file size of the geometry and decrease efficiency, and so is not\nrecommended unless disconnected vertices (\"vertex soup\") are required for some\nparticular software application.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(unweld(options as unknown as UnweldOptions)),\n\t);\n\n// TANGENTS\nprogram\n\t.command('tangents', 'Generate MikkTSpace vertex tangents')\n\t.help(\n\t\t`\nGenerates MikkTSpace vertex tangents.\n\nIn some situations normal maps may appear incorrectly, displaying hard edges\nat seams, or unexpectedly inverted insets and extrusions. The issue is most\ncommonly caused by a mismatch between the software used to bake the normal map\nand the pixel shader or other code used to render it. While this may be a\nfrustration to an artist/designer, it is not always possible for the rendering\nengine to reconstruct the tangent space used by the authoring software.\n\nMost normal map bakers use the MikkTSpace standard (http://www.mikktspace.com/)\nto generate vertex tangents while creating a normal map, and the technique is\nrecommended by the glTF 2.0 specification. Generating vertex tangents with this\ntool may resolve rendering issues related to normal maps in engines that cannot\ncompute MikkTSpace tangents at runtime.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--overwrite', 'Overwrite existing vertex tangents', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(\n\t\t\tunweld(),\n\t\t\ttangents({ generateTangents: mikktspace.generateTangents, ...options }),\n\t\t\tweld(),\n\t\t),\n\t);\n\n// UNWRAP\nprogram\n\t.command('unwrap', 'Generate texcoords')\n\t.help(\n\t\t`\nGenerates texture coordinates for the given attribute set index.\n\nUses xatlas (https://github.com/jpcy/xatlas) to generate unique texture\ncoordinates suitable for baking lightmaps or texture painting.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--texcoord <index>', 'Target texture coordinate index. 0 = TEXCOORD_0, etc.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: 0,\n\t})\n\t.option('--overwrite', 'Overwrite existing vertex tangents', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.option('--group-by <type>', 'Grouping of texture coordinates for generated atlases', {\n\t\tvalidator: ['primitive', 'mesh', 'scene'],\n\t\tdefault: UNWRAP_DEFAULTS.groupBy,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(unwrap({ watlas, ...options })),\n\t);\n\n// REORDER\nprogram\n\t.command('reorder', 'Optimize vertex data for locality of reference')\n\t.help(\n\t\t`\nOptimize vertex data for locality of reference.\n\nChoose whether the order should be optimal for transmission size (recommended for Web) or for GPU\nrendering performance. When optimizing for transmission size, reordering is expected to be a pre-\nprocessing step before applying Meshopt compression and lossless supercompression (such as gzip or\nbrotli). Reordering will only reduce size when used in combination with other compression methods.\n\nBased on the meshoptimizer library (https://github.com/zeux/meshoptimizer).\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--target', 'Whether to optimize for transmission size or GPU performance', {\n\t\tvalidator: ['size', 'performance'],\n\t\tdefault: 'size',\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(reorder({ encoder: MeshoptEncoder, ...options })),\n\t);\n\n// SIMPLIFY\nprogram\n\t.command('simplify', 'Simplify mesh, reducing number of vertices')\n\t.help(\n\t\t`\nSimplify mesh, reducing number of vertices.\n\nSimplification algorithm producing meshes with fewer triangles and\nvertices. Simplification is lossy, but the algorithm aims to\npreserve visual quality as much as possible, for given parameters.\n\nThe algorithm aims to reach the target --ratio, while minimizing error. If\nerror exceeds the specified --error threshold, the algorithm will quit\nbefore reaching the target ratio. Examples:\n\n- ratio=0.5, error=0.001: Aims for 50% simplification, constrained to 0.1% error.\n- ratio=0.5, error=1: Aims for 50% simplification, unconstrained by error.\n- ratio=0.0, error=0.01: Aims for maximum simplification, constrained to 1% error.\n\nTopology, particularly split vertices, will also limit the simplifier. For\nbest results, apply a 'weld' operation before simplification.\n\nBased on the meshoptimizer library (https://github.com/zeux/meshoptimizer).\n`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--ratio <ratio>', 'Target ratio (0–1) of vertices to keep', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: SIMPLIFY_DEFAULTS.ratio,\n\t})\n\t.option('--error <error>', 'Limit on error, as a fraction of mesh radius', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: SIMPLIFY_DEFAULTS.error,\n\t})\n\t.option('--lock-border <bool>', 'Whether to lock topological borders of the mesh', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: SIMPLIFY_DEFAULTS.lockBorder,\n\t})\n\t.action(async ({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(\n\t\t\tsimplify({ simplifier: MeshoptSimplifier, ...options }),\n\t\t),\n\t);\n\nprogram.section('Material', '🎨');\n\n// METALROUGH\nprogram\n\t.command('metalrough', 'Convert materials from spec/gloss to metal/rough')\n\t.help(\n\t\t`\nConvert materials from spec/gloss to metal/rough. In general, the metal/rough\nworkflow is better supported, more compact, and more future-proof. All features\nof the spec/gloss workflow can be converted to metal/rough, as long as the\nKHR_materials_specular and KHR_materials_ior extensions are supported. When one\nor both of those extensions are not supported, metallic materials may require\nfurther adjustments after the conversion.\n\nThis conversion rewrites spec/gloss textures, and the resulting textures may\nhave less optimal compression than the original. Ideally, lossless PNG textures\nshould be used as input, and then compressed after this conversion.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, logger }) => Session.create(io, logger, args.input, args.output).transform(metalRough()));\n\n// PALETTE\nprogram\n\t.command('palette', 'Creates palette textures and merges materials')\n\t.help(\n\t\t`\nCreates palette textures containing all unique values of scalar Material\nproperties within the scene, then merges materials. For scenes with many\nsolid-colored materials (often found in CAD, architectural, or low-poly\nstyles), texture palettes can reduce the number of materials used, and\nsignificantly increase the number of Mesh objects eligible for \"join\"\noperations.\n\nMaterials already containing texture coordinates (UVs) are not eligible for\ntexture palette optimizations. Currently only a material's base color,\nalpha, emissive factor, metallic factor, and roughness factor are converted\nto palette textures.\n`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--block-size <px>', 'Size (in pixels) of a single block within each palette texture.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: PALETTE_DEFAULTS.blockSize,\n\t})\n\t.option(\n\t\t'--min <count>',\n\t\t'Minimum number of blocks in the palette texture. If fewer unique ' +\n\t\t\t'material values are found, no palettes will be generated.',\n\t\t{\n\t\t\tvalidator: Validator.NUMBER,\n\t\t\tdefault: PALETTE_DEFAULTS.min,\n\t\t},\n\t)\n\t.action(async ({ args, options, logger }) => {\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\tpalette(options as unknown as PaletteOptions),\n\t\t);\n\t});\n\n// UNLIT\nprogram\n\t.command('unlit', 'Convert materials from metal/rough to unlit')\n\t.help(\n\t\t`\nConvert materials to an unlit, shadeless model. Unlit materials are not\naffected by scene lighting, and can be rendered very efficiently on less\ncapable mobile devices. If device framerate is high when an object occupies a\nsmall part of the viewport, and low when that object fills the viewport, it's\nlikely that the GPU is fragment shader bound, and a simpler material (such as\nan unlit material) may improve performance.\n\nUnlit materials are also helpful for non-physically-based visual styles.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, logger }) => Session.create(io, logger, args.input, args.output).transform(unlit()));\n\nprogram.section('Texture', '🖼');\n\n// RESIZE\nprogram\n\t.command('resize', 'Resize PNG or JPEG textures')\n\t.help(\n\t\t`\nResize PNG or JPEG textures with Lanczos3 (sharp) or Lanczos2 (smooth)\nfiltering. Typically Lanczos3 is the best method, but Lanczos2 may be helpful\nto reduce ringing artifacts in some cases.\n\nLimits --width and --height are applied as maximum dimensions for each texture,\npreserving original aspect ratio. Texture dimensions are never increased.\n`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--filter', 'Resampling filter', {\n\t\tvalidator: [TextureResizeFilter.LANCZOS3, TextureResizeFilter.LANCZOS2],\n\t\tdefault: TextureResizeFilter.LANCZOS3,\n\t})\n\t.option('--width <pixels>', 'Maximum width (px) of output textures.', {\n\t\tvalidator: Validator.NUMBER,\n\t})\n\t.option('--height <pixels>', 'Maximum height (px) of output textures.', {\n\t\tvalidator: Validator.NUMBER,\n\t})\n\t.option('--power-of-two <pot>', 'Resize in two dimensions. Overrides --width and --height.', {\n\t\tvalidator: ['nearest', 'ceil', 'floor'],\n\t})\n\t.action(async ({ args, options, logger }) => {\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst { default: encoder } = await import('sharp');\n\n\t\ttype Preset = 'nearest-pot' | 'ceil-pot' | 'floor-pot';\n\t\tlet resize: vec2 | Preset;\n\t\tif (options.powerOfTwo) {\n\t\t\tif (options.width || options.height) {\n\t\t\t\tlogger.warn('When --power-of-two is specified, --width and --height are ignored.');\n\t\t\t}\n\t\t\tresize = `${options.powerOfTwo}-pot` as Preset;\n\t\t} else if (Number.isInteger(options.width) && Number.isInteger(options.height)) {\n\t\t\tresize = [Number(options.width), Number(options.height)];\n\t\t} else {\n\t\t\tthrow new Error(`Must specify --width and --height, or --power-of-two.`);\n\t\t}\n\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\ttextureCompress({\n\t\t\t\tencoder,\n\t\t\t\tresize,\n\t\t\t\tresizeFilter: options.filter as TextureResizeFilter,\n\t\t\t\tpattern,\n\t\t\t}),\n\t\t);\n\t});\n\nconst BASIS_SUMMARY = `\nCompresses textures in the given file to .ktx2 GPU textures using the\n{VARIANT} Basis Universal bitstream. GPU textures offer faster GPU upload\nand less GPU memory consumption than traditional PNG or JPEG textures,\nwhich are fully uncompressed in GPU memory. GPU texture formats require\nmore attention to compression settings to get similar visual results.\n\n{DETAILS}\n\n${styleText('underline', 'Documentation')}\nhttps://gltf-transform.dev/extensions.html#khr_texture_basisu\n\n${styleText('underline', 'Dependencies')}\nKTX-Software (https://github.com/KhronosGroup/KTX-Software/)\n`;\n\n// ETC1S\nprogram\n\t.command('etc1s', 'KTX + Basis ETC1S texture compression')\n\t.help(\n\t\tBASIS_SUMMARY.replace('{VARIANT}', 'ETC1S').replace(\n\t\t\t'{DETAILS}',\n\t\t\t`\nETC1S, one of the two Basis Universal bitstreams, offers lower size and lower\nquality than UASTC. In some cases it may be useful to increase the resolution\nof the texture, to minimize compression artifacts while still retaining an\noverall smaller filesize. Consider using less aggressive compression settings\nfor normal maps than for other texture types: you may want to use UASTC for\nnormal maps and ETC1S for other textures, for example.`.trim(),\n\t\t),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--slots <slots>', 'Texture slots to include (glob)', { validator: Validator.STRING })\n\t.option('--resize <size>', 'Maximum texture dimensions, in pixels.', {\n\t\tvalidator: Validator.NUMBER,\n\t})\n\t.option('--mipmaps <bool>', 'Generate mipmaps.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: ETC1S_DEFAULTS.mipmaps,\n\t})\n\t.option('--filter <filter>', 'Specifies the filter to use when generating mipmaps.', {\n\t\tvalidator: Object.values(Filter),\n\t\tdefault: ETC1S_DEFAULTS.filter,\n\t})\n\t.option('--filter-scale <fscale>', 'Specifies the filter scale to use when generating mipmaps.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: ETC1S_DEFAULTS.filterScale,\n\t})\n\t.option(\n\t\t'--compression <clevel>',\n\t\t'Compression level, an encoding speed vs. quality tradeoff.' +\n\t\t\t' Higher values are slower, but give higher quality. Try' +\n\t\t\t' --quality before experimenting with this option.',\n\t\t{ validator: [0, 1, 2, 3, 4, 5], default: ETC1S_DEFAULTS.compression },\n\t)\n\t.option(\n\t\t'--quality <qlevel>',\n\t\t'Quality level. Range is 1 - 255. Lower gives better' +\n\t\t\t' compression, lower quality, and faster encoding. Higher gives less compression,' +\n\t\t\t' higher quality, and slower encoding. Quality level determines values of' +\n\t\t\t' --max_endpoints and --max-selectors, unless those values are explicitly set.',\n\t\t{ validator: Validator.NUMBER, default: ETC1S_DEFAULTS.quality },\n\t)\n\t.option(\n\t\t'--max-endpoints <max_endpoints>',\n\t\t'Manually set the maximum number of color endpoint clusters from' + ' 1-16128.',\n\t\t{ validator: Validator.NUMBER, default: ETC1S_DEFAULTS.maxEndpoints },\n\t)\n\t.option(\n\t\t'--max-selectors <max_selectors>',\n\t\t'Manually set the maximum number of color selector clusters from' + ' 1-16128.',\n\t\t{ validator: Validator.NUMBER, default: ETC1S_DEFAULTS.maxSelectors },\n\t)\n\t.option(\n\t\t'--rdo-threshold <rdo_threshold>',\n\t\t'Set endpoint and selector RDO quality threshold. Lower' +\n\t\t\t' is higher quality but less quality per output bit (try 1.0-3.0).' +\n\t\t\t' Overrides --quality.',\n\t\t{ validator: Validator.NUMBER, default: ETC1S_DEFAULTS.rdoThreshold },\n\t)\n\t.option(\n\t\t'--rdo',\n\t\t'Enable endpoint and selector RDO (slightly' + ' faster, less noisy output, but lower quality per output bit).',\n\t\t{ validator: Validator.BOOLEAN, default: ETC1S_DEFAULTS.rdo },\n\t)\n\t.option('--jobs <num_jobs>', 'Spawns up to num_jobs instances of toktx', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: ETC1S_DEFAULTS.jobs,\n\t})\n\t.action(async ({ args, options, logger }) => {\n\t\tconst { default: encoder } = await import('sharp');\n\t\tconst mode = Mode.ETC1S;\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst slots = options.slots ? micromatch.makeRe(String(options.slots), MICROMATCH_OPTIONS) : null;\n\t\tconst resize: vec2 | undefined = options.resize ? [Number(options.resize), Number(options.resize)] : undefined;\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\ttoktx({ ...options, encoder, mode, pattern, slots, resize }),\n\t\t);\n\t});\n\n// UASTC\nprogram\n\t.command('uastc', 'KTX + Basis UASTC texture compression')\n\t.help(\n\t\tBASIS_SUMMARY.replace('{VARIANT}', 'UASTC').replace(\n\t\t\t'{DETAILS}',\n\t\t\t`\nUASTC, one of the two Basis Universal bitstreams, offers higher size and higher\nquality than ETC1S. While it is suitable for all texture types, you may find it\nuseful to apply UASTC only where higher quality is necessary, and apply ETC1S\nfor textures where the quality is sufficient.`.trim(),\n\t\t),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--slots <slots>', 'Texture slots to include (glob)', { validator: Validator.STRING })\n\t.option('--resize <size>', 'Maximum texture dimensions, in pixels.', {\n\t\tvalidator: Validator.NUMBER,\n\t})\n\t.option('--mipmaps <bool>', 'Generate mipmaps.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: UASTC_DEFAULTS.mipmaps,\n\t})\n\t.option('--filter <filter>', 'Specifies the filter to use when generating mipmaps.', {\n\t\tvalidator: Object.values(Filter),\n\t\tdefault: UASTC_DEFAULTS.filter,\n\t})\n\t.option('--filter-scale <fscale>', 'Specifies the filter scale to use when generating mipmaps.', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: UASTC_DEFAULTS.filterScale,\n\t})\n\t.option(\n\t\t'--level <level>',\n\t\t'Create a texture in high-quality transcodable UASTC format.' +\n\t\t\t' The optional parameter <level> selects a speed' +\n\t\t\t' vs quality tradeoff as shown in the following table:' +\n\t\t\t'\\n\\n' +\n\t\t\t'Level | Speed     | Quality' +\n\t\t\t'\\n——————|———————————|————————' +\n\t\t\t'\\n0     | Fastest   | 43.45dB' +\n\t\t\t'\\n1     | Faster    | 46.49dB' +\n\t\t\t'\\n2     | Default   | 47.47dB' +\n\t\t\t'\\n3     | Slower    | 48.01dB' +\n\t\t\t'\\n4     | Very slow | 48.24dB',\n\t\t{ validator: [0, 1, 2, 3, 4], default: UASTC_DEFAULTS.level },\n\t)\n\t.option('--rdo', 'Enable UASTC RDO post-processing.', { validator: Validator.BOOLEAN, default: UASTC_DEFAULTS.rdo })\n\t.option(\n\t\t'--rdo-lambda <uastc_rdo_l>',\n\t\t'Set UASTC RDO quality scalar (lambda). Lower values yield higher' +\n\t\t\t' quality/larger LZ compressed files, higher values yield lower' +\n\t\t\t' quality/smaller LZ compressed files. A good range to try is [.25, 10].' +\n\t\t\t' For normal maps, try [.25, .75]. Full range is [.001, 10.0].',\n\t\t{ validator: Validator.NUMBER, default: UASTC_DEFAULTS.rdoLambda },\n\t)\n\t.option(\n\t\t'--rdo-dictionary-size <uastc_rdo_d>',\n\t\t'Set UASTC RDO dictionary size in bytes. Default is 32768. Lower' +\n\t\t\t' values=faster, but give less compression. Possible range is [256, 65536].',\n\t\t{ validator: Validator.NUMBER, default: UASTC_DEFAULTS.rdoDictionarySize },\n\t)\n\t.option(\n\t\t'--rdo-block-scale <uastc_rdo_b>',\n\t\t'Set UASTC RDO max smooth block error scale. Range is [1.0, 300.0].' +\n\t\t\t' Default is 10.0, 1.0 is disabled. Larger values suppress more' +\n\t\t\t' artifacts (and allocate more bits) on smooth blocks.',\n\t\t{ validator: Validator.NUMBER, default: UASTC_DEFAULTS.rdoBlockScale },\n\t)\n\t.option(\n\t\t'--rdo-std-dev <uastc_rdo_s>',\n\t\t'Set UASTC RDO max smooth block standard deviation. Range is' +\n\t\t\t' [.01, 65536.0]. Default is 18.0. Larger values expand the range' +\n\t\t\t' of blocks considered smooth.',\n\t\t{ validator: Validator.NUMBER, default: UASTC_DEFAULTS.rdoStdDev },\n\t)\n\t.option(\n\t\t'--rdo-multithreading <uastc_rdo_m>',\n\t\t'Enable RDO multithreading (slightly lower compression, non-deterministic).',\n\t\t{ validator: Validator.BOOLEAN, default: UASTC_DEFAULTS.rdoMultithreading },\n\t)\n\t.option(\n\t\t'--zstd <compressionLevel>',\n\t\t'Supercompress the data with Zstandard.' +\n\t\t\t' Compression level range is [1, 22], or 0 is uncompressed.' +\n\t\t\t' Lower values decode faster but offer less compression. Values above' +\n\t\t\t' 20 should be used with caution, requiring more memory to decompress:' +\n\t\t\t'\\n\\n' +\n\t\t\t// Sources:\n\t\t\t// - https://news.ycombinator.com/item?id=13814475\n\t\t\t// - https://github.com/facebook/zstd/blob/15a7a99653c78a57d1ccbf5c5b4571e62183bf4f/lib/compress/zstd_compress.c#L3250\n\t\t\t'Level | Window Size ' +\n\t\t\t'\\n——————|—————————————' +\n\t\t\t'\\n1     |      256 KB ' +\n\t\t\t'\\n…     |           … ' +\n\t\t\t'\\n10    |        2 MB ' +\n\t\t\t'\\n…     |           … ' +\n\t\t\t'\\n18    |        8 MB ' +\n\t\t\t'\\n19    |        8 MB ' +\n\t\t\t'\\n20    |       34 MB ' +\n\t\t\t'\\n21    |       67 MB ' +\n\t\t\t'\\n22    |      134 MB ',\n\t\t{ validator: Validator.NUMBER, default: UASTC_DEFAULTS.zstd },\n\t)\n\t.option('--jobs <num_jobs>', 'Spawns up to num_jobs instances of toktx', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: UASTC_DEFAULTS.jobs,\n\t})\n\t.action(async ({ args, options, logger }) => {\n\t\tconst { default: encoder } = await import('sharp');\n\t\tconst mode = Mode.UASTC;\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst slots = options.slots ? micromatch.makeRe(String(options.slots), MICROMATCH_OPTIONS) : null;\n\t\tconst resize: vec2 | undefined = options.resize ? [Number(options.resize), Number(options.resize)] : undefined;\n\t\tSession.create(io, logger, args.input, args.output).transform(\n\t\t\ttoktx({ ...options, encoder, mode, pattern, slots, resize }),\n\t\t);\n\t});\n\n// KTXDECOMPRESS\nprogram\n\t.command('ktxdecompress', 'KTX + Basis texture decompression')\n\t.help(\n\t\t`\n\t\tDecompresses KTX2 textures in KTX2 format, converting to PNG.\n\t\tIntended for debugging, or to resolve compatibility issues in\n\t\tsoftware that doesn't support KTX2 textures.`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, logger }) => Session.create(io, logger, args.input, args.output).transform(ktxdecompress()));\n\n// KTXFIX\nprogram\n\t.command('ktxfix', 'Fixes common issues in KTX texture metadata')\n\t.help(\n\t\t`\nCertain KTX texture metadata was written incorrectly in early (pre-release)\nsoftware. In particular, viewers may misinterpret color primaries as sRGB\nincorrectly when a texture exhibits this issue.\n\nThis command determines correct color primaries based on usage in the glTF\nfile, and updates the KTX texture accordingly. The change is lossless, and\naffects only the container metadata.`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, logger }) => Session.create(io, logger, args.input, args.output).transform(ktxfix()));\n\nconst TEXTURE_COMPRESS_SUMMARY = `\nCompresses textures with {VARIANT}, using sharp. Reduces transmitted file\nsize. Compared to GPU texture compression like KTX/Basis, PNG/JPEG/WebP must\nbe fully decompressed in GPU memory — this makes texture GPU upload much\nslower, and may consume 4-8x more GPU memory. However, the PNG/JPEG/WebP\ncompression methods are typically more forgiving than GPU texture compression,\nand require less tuning to achieve good visual and filesize results.\n`.trim();\n\n// AVIF\n// IMPORTANT: No defaults for quality flags, see https://github.com/donmccurdy/glTF-Transform/issues/969.\nprogram\n\t.command('avif', 'AVIF texture compression')\n\t.help(TEXTURE_COMPRESS_SUMMARY.replace(/{VARIANT}/g, 'AVIF'))\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--formats <formats>', 'Texture formats to include', {\n\t\tvalidator: [...TEXTURE_COMPRESS_SUPPORTED_FORMATS, '*'],\n\t\tdefault: '*',\n\t})\n\t.option('--slots <slots>', 'Texture slots to include (glob)', { validator: Validator.STRING, default: '*' })\n\t.option('--quality <quality>', 'Quality, 1-100', { validator: Validator.NUMBER })\n\t.option('--effort <effort>', 'Level of CPU effort to reduce file size, 0-100', { validator: Validator.NUMBER })\n\t.option('--lossless <lossless>', 'Use lossless compression mode', { validator: Validator.BOOLEAN, default: false })\n\t.action(async ({ args, options, logger }) => {\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst formats = regexFromArray([options.formats] as string[]);\n\t\tconst slots = micromatch.makeRe(String(options.slots), MICROMATCH_OPTIONS);\n\t\tconst { default: encoder } = await import('sharp');\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\ttextureCompress({\n\t\t\t\ttargetFormat: 'avif',\n\t\t\t\tencoder,\n\t\t\t\tpattern,\n\t\t\t\tformats,\n\t\t\t\tslots,\n\t\t\t\tquality: options.quality as number,\n\t\t\t\teffort: options.effort as number,\n\t\t\t\tlossless: options.lossless as boolean,\n\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t}),\n\t\t);\n\t});\n\n// WEBP\n// IMPORTANT: No defaults for quality flags, see https://github.com/donmccurdy/glTF-Transform/issues/969.\nprogram\n\t.command('webp', 'WebP texture compression')\n\t.help(TEXTURE_COMPRESS_SUMMARY.replace(/{VARIANT}/g, 'WebP'))\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--formats <formats>', 'Texture formats to include', {\n\t\tvalidator: [...TEXTURE_COMPRESS_SUPPORTED_FORMATS, '*'],\n\t\tdefault: '*',\n\t})\n\t.option('--slots <slots>', 'Texture slots to include (glob)', { validator: Validator.STRING, default: '*' })\n\t.option('--quality <quality>', 'Quality, 1-100', { validator: Validator.NUMBER })\n\t.option('--effort <effort>', 'Level of CPU effort to reduce file size, 0-100', { validator: Validator.NUMBER })\n\t.option('--lossless <lossless>', 'Use lossless compression mode', { validator: Validator.BOOLEAN, default: false })\n\t.option('--near-lossless <nearLossless>', 'Use near lossless compression mode.', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: false,\n\t})\n\t.action(async ({ args, options, logger }) => {\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst formats = regexFromArray([options.formats] as string[]);\n\t\tconst slots = micromatch.makeRe(String(options.slots), MICROMATCH_OPTIONS);\n\t\tconst { default: encoder } = await import('sharp');\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\ttextureCompress({\n\t\t\t\ttargetFormat: 'webp',\n\t\t\t\tencoder,\n\t\t\t\tpattern,\n\t\t\t\tformats,\n\t\t\t\tslots,\n\t\t\t\tquality: options.quality as number,\n\t\t\t\teffort: options.effort as number,\n\t\t\t\tlossless: options.lossless as boolean,\n\t\t\t\tnearLossless: options.nearLossless as boolean,\n\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t}),\n\t\t);\n\t});\n\n// PNG\n// IMPORTANT: No defaults for quality flags, see https://github.com/donmccurdy/glTF-Transform/issues/969.\nprogram\n\t.command('png', 'PNG texture compression')\n\t.help(TEXTURE_COMPRESS_SUMMARY.replace(/{VARIANT}/g, 'PNG'))\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--formats <formats>', 'Texture formats to include', {\n\t\tvalidator: [...TEXTURE_COMPRESS_SUPPORTED_FORMATS, '*'],\n\t\tdefault: 'png',\n\t})\n\t.option('--slots <slots>', 'Texture slots to include (glob)', { validator: Validator.STRING, default: '*' })\n\t.option('--quality <quality>', 'Quality, 1-100', { validator: Validator.NUMBER })\n\t.option('--effort <effort>', 'Level of CPU effort to reduce file size, 0-100', { validator: Validator.NUMBER })\n\t.action(async ({ args, options, logger }) => {\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst formats = regexFromArray([options.formats] as string[]);\n\t\tconst slots = micromatch.makeRe(String(options.slots), MICROMATCH_OPTIONS);\n\t\tconst { default: encoder } = await import('sharp');\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\ttextureCompress({\n\t\t\t\ttargetFormat: 'png',\n\t\t\t\tencoder,\n\t\t\t\tpattern,\n\t\t\t\tformats,\n\t\t\t\tslots,\n\t\t\t\tquality: options.quality as number,\n\t\t\t\teffort: options.effort as number,\n\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t}),\n\t\t);\n\t});\n\n// JPEG\n// IMPORTANT: No defaults for quality flags, see https://github.com/donmccurdy/glTF-Transform/issues/969.\nprogram\n\t.command('jpeg', 'JPEG texture compression')\n\t.help(TEXTURE_COMPRESS_SUMMARY.replace(/{VARIANT}/g, 'JPEG'))\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--pattern <pattern>', 'Pattern (glob) to match textures, by name or URI.', {\n\t\tvalidator: Validator.STRING,\n\t})\n\t.option('--formats <formats>', 'Texture formats to include', {\n\t\tvalidator: [...TEXTURE_COMPRESS_SUPPORTED_FORMATS, '*'],\n\t\tdefault: 'jpeg',\n\t})\n\t.option('--slots <slots>', 'Texture slots to include (glob)', { validator: Validator.STRING, default: '*' })\n\t.option('--quality <quality>', 'Quality, 1-100', { validator: Validator.NUMBER })\n\t.action(async ({ args, options, logger }) => {\n\t\tconst pattern = options.pattern ? micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS) : null;\n\t\tconst formats = regexFromArray([options.formats] as string[]);\n\t\tconst slots = micromatch.makeRe(String(options.slots), MICROMATCH_OPTIONS);\n\t\tconst { default: encoder } = await import('sharp');\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\ttextureCompress({\n\t\t\t\ttargetFormat: 'jpeg',\n\t\t\t\tencoder,\n\t\t\t\tpattern,\n\t\t\t\tformats,\n\t\t\t\tslots,\n\t\t\t\tquality: options.quality as number,\n\t\t\t\tlimitInputPixels: options.limitInputPixels as boolean,\n\t\t\t}),\n\t\t);\n\t});\n\nprogram.section('Animation', '⏯️');\n\n// RESAMPLE\nprogram\n\t.command('resample', 'Resample animations, losslessly deduplicating keyframes')\n\t.help(\n\t\t`\nResample animations, losslessly deduplicating keyframes. Exporters sometimes\nneed to \"bake\" animations, writing data for 20-30 frames per second, in order\nto correctly represent IK constraints and other animation techniques. These\nadditional keyframes are often redundant — particularly with morph targets —\nas engines can interpolate animation at 60–120 FPS even with sparse keyframes.\n\nThe resampling process removes redundant keyframes from animations using STEP\nand LINEAR interpolation. Resampling is nearly lossless, with configurable\n--tolerance, and should have no visible effect on animation playback.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--tolerance', 'Per-value tolerance to merge similar keyframes', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: 1e-4,\n\t})\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(\n\t\t\tresample({\n\t\t\t\tready: resampleReady,\n\t\t\t\tresample: resampleWASM,\n\t\t\t\t...(options as unknown as ResampleOptions),\n\t\t\t}),\n\t\t),\n\t);\n\n// SEQUENCE\nprogram\n\t.command('sequence', 'Animate node visibilities as a flipboard sequence')\n\t.help(\n\t\t`\nAnimate node visibilities as a flipboard sequence. An example workflow would\nbe to create a .glb containing one geometry for each frame of a complex\nanimation that can't be represented as TRS, skinning, or morph targets. The\nsequence function generates a new animation, playing back each mesh matching\nthe given pattern, at a specific framerate. Displaying a sequence of textures\nis also supported, but note that texture memory usage may be quite high and\nso this workflow is not a replacement for video playback.\n\t`.trim(),\n\t)\n\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.option('--name <name>', 'Name of new animation', {\n\t\tvalidator: Validator.STRING,\n\t\tdefault: '',\n\t})\n\t.option('--pattern <pattern>', 'Pattern for node names (case-insensitive glob)', {\n\t\tvalidator: Validator.STRING,\n\t\trequired: true,\n\t})\n\t.option('--fps <fps>', 'FPS (frames / second)', {\n\t\tvalidator: Validator.NUMBER,\n\t\tdefault: 10,\n\t})\n\t.option('--sort <sort>', 'Order sequence by node name', {\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t})\n\t.action(({ args, options, logger }) => {\n\t\tconst pattern = micromatch.makeRe(String(options.pattern), MICROMATCH_OPTIONS);\n\t\treturn Session.create(io, logger, args.input, args.output).transform(\n\t\t\tsequence({ ...options, pattern } as SequenceOptions),\n\t\t);\n\t});\n\n// SPARSE\nprogram\n\t.command('sparse', 'Reduces storage for zero-filled arrays')\n\t.help(\n\t\t`\nScans all Accessors in the Document, detecting whether each Accessor would\nbenefit from sparse data storage. Currently, sparse data storage is used only\nwhen many values (>= 1/3) are zeroes. Particularly for assets using morph\ntarget (\"shape key\") animation, sparse data storage may significantly reduce\nfile sizes.\n\t`.trim(),\n\t)\n\t.argument('<input>', INPUT_DESC)\n\t.argument('<output>', OUTPUT_DESC)\n\t.action(({ args, options, logger }) =>\n\t\tSession.create(io, logger, args.input, args.output).transform(sparse(options as unknown as SparseOptions)),\n\t);\n\nprogram.option('--allow-net', 'Allows reads from network requests.', {\n\tdefault: false,\n\tvalidator: Validator.BOOLEAN,\n\taction: ({ options }) => {\n\t\tif (options.allowNet) io.setAllowNetwork(true);\n\t},\n});\nprogram.option('--vertex-layout <layout>', 'Vertex buffer layout preset.', {\n\tdefault: VertexLayout.INTERLEAVED,\n\tvalidator: [VertexLayout.INTERLEAVED, VertexLayout.SEPARATE],\n\taction: ({ options }) => {\n\t\tio.setVertexLayout(options.vertexLayout as VertexLayout);\n\t},\n});\nprogram.option('--config <path>', 'Installs custom commands or extensions. (EXPERIMENTAL)', {\n\tvalidator: Validator.STRING,\n});\nprogram.option(\n\t'--limit-input-pixels',\n\t'Attempts to avoid processing very high resolution images, where memory or ' +\n\t\t'other limits may be exceeded. (EXPERIMENTAL)',\n\t{\n\t\tvalidator: Validator.BOOLEAN,\n\t\tdefault: true,\n\t\thidden: true,\n\t},\n);\nprogram.disableGlobalOption('--quiet');\nprogram.disableGlobalOption('--no-color');\n\nexport * from './transforms/index.js';\nexport * from './utils/format.js'; // unit testing\nexport * from './utils/log.js'; // unit testing\nexport * from './utils/p-limit.js'; // unit testing\nexport * from './utils/process.js'; // unit testing\nexport { program, programReady, Validator };\n"],"mappings":"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"}