From 79ed96de998eee5089ac170135c507ab165276bb Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Thu, 19 Feb 2026 12:47:49 -0600 Subject: [PATCH 1/6] Introduced ability to view/export the full scene item tree for a scene --- package.json | 8 +- src/commands/scene-trees/export.ts | 53 +++ src/commands/scene-trees/view.ts | 39 +++ src/lib/scene-items.ts | 45 +++ src/lib/tree-builder.ts | 75 +++++ src/lib/tree-node.ts | 165 +++++++++ src/lib/tree-serializer.ts | 280 ++++++++++++++++ test/commands/scene-trees/export.test.ts | 70 ++++ test/commands/scene-trees/view.test.ts | 44 +++ yarn.lock | 404 ++++++++++++++++++++++- 10 files changed, 1176 insertions(+), 7 deletions(-) create mode 100644 src/commands/scene-trees/export.ts create mode 100644 src/commands/scene-trees/view.ts create mode 100644 src/lib/scene-items.ts create mode 100644 src/lib/tree-builder.ts create mode 100644 src/lib/tree-node.ts create mode 100644 src/lib/tree-serializer.ts create mode 100644 test/commands/scene-trees/export.test.ts create mode 100644 test/commands/scene-trees/view.test.ts diff --git a/package.json b/package.json index 15b92fb..3d6f10f 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@oclif/config": "^1.18.9", "@oclif/plugin-help": "^3.3.1", "@vertexvis/api-client-node": "^0.33.2", + "archiver": "^7.0.1", "cli-ux": "^5.6.7", "fast-xml-parser": "^3.21", "fs-extra": "^10.1.0", @@ -37,6 +38,7 @@ "@oclif/dev-cli": "^1", "@oclif/parser": "^3.8", "@oclif/test": "^1.2", + "@types/archiver": "^7.0.0", "@types/chai": "^4.3", "@types/fs-extra": "^9.0", "@types/mocha": "^9", @@ -93,6 +95,9 @@ "scene-views": { "description": "Scene view CRUD operations." }, + "scene-trees": { + "description": "Scene item tree operations." + }, "scenes": { "description": "Scene CRUD operations." }, @@ -117,5 +122,6 @@ "setup": "yarn && yarn link", "test": "nyc mocha", "version": "oclif-dev readme && git add README.md" - } + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" } diff --git a/src/commands/scene-trees/export.ts b/src/commands/scene-trees/export.ts new file mode 100644 index 0000000..235e3b2 --- /dev/null +++ b/src/commands/scene-trees/export.ts @@ -0,0 +1,53 @@ +import { flags } from '@oclif/command'; +import { logError, VertexError } from '@vertexvis/api-client-node'; + +import BaseCommand from '../../lib/base'; +import { vertexClient } from '../../lib/client'; +import { fetchSceneItemTree } from '../../lib/scene-items'; +import { serializeTreeToZipFile } from '../../lib/tree-serializer'; + +export default class Export extends BaseCommand { + public static description = `Export a scene's scene item tree to a ZIP file.`; + + public static examples = [ + `$ vertex scene-trees:export 54964c61-05d8-4f37-9638-18f7c4960c80 +Tree saved to: 54964c61-05d8-4f37-9638-18f7c4960c80.zip +`, + ]; + + public static args = [{ name: 'sceneId', required: true }]; + + public static flags = { + ...BaseCommand.flags, + output: flags.string({ + char: 'o', + description: 'Output file path.', + }), + }; + + public async run(): Promise { + const { + args: { sceneId }, + flags: { output }, + } = this.parse(Export); + const basePath = this.parsedFlags?.basePath; + const filePath = output ?? `${sceneId}.zip`; + + try { + this.log(`Fetching scene item tree for scene ID: ${sceneId}...`); + const root = await fetchSceneItemTree( + await vertexClient(basePath, this.userConfig), + sceneId + ); + this.log(`Fetched ${root.size} scene items. Saving to file...`); + await serializeTreeToZipFile({ + root, + filePath, + entryName: `${sceneId}.json`, + }); + this.log(`Tree saved to: ${filePath}`); + } catch (error) { + logError(error as VertexError, this.error); + } + } +} diff --git a/src/commands/scene-trees/view.ts b/src/commands/scene-trees/view.ts new file mode 100644 index 0000000..ac35e37 --- /dev/null +++ b/src/commands/scene-trees/view.ts @@ -0,0 +1,39 @@ +import { logError, VertexError } from '@vertexvis/api-client-node'; + +import BaseCommand from '../../lib/base'; +import { vertexClient } from '../../lib/client'; +import { fetchSceneItemTree } from '../../lib/scene-items'; + +export default class View extends BaseCommand { + public static description = `View a scene's item tree.`; + + public static examples = [ + `$ vertex scene-trees:view 54964c61-05d8-4f37-9638-18f7c4960c80 +[TreeNode (root) has 3 child nodes, data=[...]] +└── [TreeNode has 2 child nodes, data=[...]] +`, + ]; + + public static args = [{ name: 'sceneId', required: true }]; + + public static flags = BaseCommand.flags; + + public async run(): Promise { + const { + args: { sceneId }, + } = this.parse(View); + const basePath = this.parsedFlags?.basePath; + + try { + this.log(`Fetching scene item tree for scene ID: ${sceneId}...`); + const root = await fetchSceneItemTree( + await vertexClient(basePath, this.userConfig), + sceneId + ); + this.log(`Fetched ${root.size} scene items.`); + this.log(root.dump()); + } catch (error) { + logError(error as VertexError, this.error); + } + } +} diff --git a/src/lib/scene-items.ts b/src/lib/scene-items.ts new file mode 100644 index 0000000..cbd966e --- /dev/null +++ b/src/lib/scene-items.ts @@ -0,0 +1,45 @@ +import { + getPage, + SceneItemData, + VertexClient, +} from '@vertexvis/api-client-node'; + +import { buildTreeFromFlat } from './tree-builder'; +import { TreeNode } from './tree-node'; + +export async function fetchAllSceneItemsForScene( + client: VertexClient, + sceneId: string +): Promise { + const sceneItemSets: SceneItemData[][] = []; + let cursor: string | undefined; + let itemsRemain = true; + while (itemsRemain) { + // eslint-disable-next-line no-await-in-loop + const res = await getPage(() => + client.sceneItems.getSceneItems({ + id: sceneId, + pageSize: 200, + pageCursor: cursor, + }) + ); + cursor = res.cursor; + if (cursor === undefined) { + itemsRemain = false; + } + sceneItemSets.push(res.page.data); + } + return sceneItemSets.flat(); +} + +export async function fetchSceneItemTree( + client: VertexClient, + sceneId: string +): Promise> { + const allSceneItems = await fetchAllSceneItemsForScene(client, sceneId); + return buildTreeFromFlat( + allSceneItems, + (rec) => rec.id, + (rec) => rec.relationships.parent?.data.id + )[0]; +} diff --git a/src/lib/tree-builder.ts b/src/lib/tree-builder.ts new file mode 100644 index 0000000..04c033c --- /dev/null +++ b/src/lib/tree-builder.ts @@ -0,0 +1,75 @@ +import { TreeNode } from './tree-node'; + +/* + * Given any object T that may have a `children?: T[]`, + * recursively build a TreeNode subtree. + */ +export function buildTreeFromNested( + record: T, + parent?: TreeNode +): TreeNode { + // auto-links to parent if provided + const node = new TreeNode(record, parent); + for (const child of record.children ?? []) { + buildTreeFromNested(child, node); + } + return node; +} + +/** + * Given a flat array of objects T, build a forest of TreeNode trees. + * This is useful for converting a flat list of records with resolvable + * parent-child relationships into a tree structure. + * @param data Array of records to convert + * @param dataIdFunction Function to extract the unique key for each record (default: rec.id) + * @param parentIdFunction Function to extract the parent key for each record (default: rec.parentId) + * @returns Array of root TreeNode instances representing the forest + * @example + * // Given a flat list of records with parent-child relationships: + * const records = [ + * { id: '1', parentId: undefined, name: 'Root' }, + * { id: '2', parentId: '1', name: 'Child 1' }, + * { id: '3', parentId: '1', name: 'Child 2' }, + * { id: '4', parentId: '2', name: 'Grandchild 1' }, + * ]; + * // Build the tree structure: + * const tree = buildTreeFromFlat(records, rec => rec.id, rec => rec.parentId); + * // Resulting tree structure: + * // [ + * // TreeNode { data: { id: '1', parentId: undefined, name: 'Root' }, children: [ + * // TreeNode { data: { id: '2', parentId: '1', name: 'Child 1' }, children: [ + * // TreeNode { data: { id: '4', parentId: '2', name: 'Grandchild 1' }, children: [] } + * // ] }, + * // TreeNode { data: { id: '3', parentId: '1', name: 'Child 2' }, children: [] } + * // ] } + * // ] + */ +export function buildTreeFromFlat( + data: T[], + dataIdFunction: (rec: T) => string, + parentIdFunction: (rec: T) => string | undefined +): TreeNode[] { + // 1) Create a TreeNode for every record, keyed by id + const nodeMap = new Map>(); + for (const rec of data) { + nodeMap.set(dataIdFunction(rec), new TreeNode(rec)); + } + + // 2) Link parents & children + const roots: TreeNode[] = []; + for (const rec of data) { + const node = nodeMap.get(dataIdFunction(rec))!; + const parentId = parentIdFunction(rec); + const parent = parentId ? nodeMap.get(parentId) ?? null : null; + if (parent === null) { + // no parent, must be a root + roots.push(node); + } else { + // attach as child + node.parent = parent; + parent.children.push(node); + } + } + + return roots; +} diff --git a/src/lib/tree-node.ts b/src/lib/tree-node.ts new file mode 100644 index 0000000..fa6ac3c --- /dev/null +++ b/src/lib/tree-node.ts @@ -0,0 +1,165 @@ +/** + * A simple tree node class that can be used to create a tree structure. + * Each node can have multiple children and a single parent. + * The class provides methods to traverse the tree, check properties of nodes, + * and manipulate the tree structure. + * + * @template T The type of the data stored in the node. + * @class TreeNode + * @implements {Iterable>} + * @property {TreeNode | null} parent - The parent node of this node. + * @property {TreeNode[]} children - The child nodes of this node. + * @property {T | null} data - The data stored in this node. + * @property {number} size - The total number of nodes in this subtree (including this node). + * @property {number} depth - The distance from this node up to the root (root.depth === 0). + * @property {number} numChildren - The number of direct children of this node. + * @property {number} numSiblings - The number of siblings (including this node). + * @property {boolean} isRoot - Returns true if this node is the root of the tree. + * @property {boolean} isLeaf - Returns true if this node is a leaf (has no children). + * @property {boolean} hasChildren - Returns true if this node has children. + * @property {boolean} hasSiblings - Returns true if this node has siblings. + * @property {boolean} isEmpty - Returns true if this node has no children. + * @example + * const root = new TreeNode('root') + * const a = new TreeNode('child A', root) + * new TreeNode('grandchild A1', a) + * new TreeNode('child B', root) + */ +export class TreeNode implements Iterable> { + public parent: TreeNode | null = null; + public children: TreeNode[] = []; + public data: T | null; + + public constructor(data: T | null = null, parent?: TreeNode) { + this.data = data; + if (parent) { + this.parent = parent; + parent.children.push(this); + } + } + + // Pre-order traversal generator + public static *preorder(node: TreeNode): Generator> { + yield node; + for (const child of node.children) { + yield* TreeNode.preorder(child); + } + } + + // Total number of nodes in this subtree (includes this node) + public get size(): number { + let count = 1; + for (const child of this.children) { + count += child.size; + } + return count; + } + + // Distance from this node up to the root (root.depth === 0) + public get depth(): number { + let d = 0; + let current = this.parent; + while (current !== null) { + d++; + current = current.parent; + } + return d; + } + + // Number of direct children + public get numChildren(): number { + return this.children.length; + } + + // Number of siblings (including this node) + public get numSiblings(): number { + return this.parent ? this.parent.children.length : 0; + } + + public isRoot(): boolean { + return this.parent === null; + } + + public isLeaf(): boolean { + return this.children.length === 0; + } + + public hasChildren(): boolean { + return this.children.length > 0; + } + + public hasSiblings(): boolean { + return this.parent !== null && this.parent.children.length > 1; + } + + public isEmpty(): boolean { + return this.children.length === 0; + } + + // Allow `for (const n of someNode) { ... }` + public [Symbol.iterator](): Iterator> { + return TreeNode.preorder(this); + } + + // True if any node in this subtree holds `obj` (by `===`) + public contains(obj: T): boolean { + for (const node of this) { + if (node.data === obj) return true; + } + return false; + } + + // Remove all descendants (but not this node itself) + public clear(): void { + for (const child of this.children) { + child.clear(); + } + this.children = []; + } + + // Grab the data payload in pre-order as a flat array + public toArray(): (T | null)[] { + const out: (T | null)[] = []; + for (const node of TreeNode.preorder(this)) { + out.push(node.data); + } + return out; + } + + public toString({ + node, + data, + }: { + node?: (node: TreeNode) => string; + data?: (data: T | null) => string; + } = {}): string { + const role = this.isRoot() ? '(root)' : ''; + const childInfo = this.isLeaf() + ? '(leaf)' + : `has ${this.children.length.toString()} child node${ + this.children.length === 1 ? '' : 's' + }`; + return node + ? node(this) + : `[TreeNode ${role} ${childInfo}, data=[${ + data ? data(this.data) : JSON.stringify(this.data).slice(0, 160) + }]]`; + } + + // Human-readable dump with ASCII-tree lines + public dump({ + node, + data, + }: { + node?: (node: TreeNode) => string; + data?: (data: T | null) => string; + } = {}): string { + let result = ''; + for (const treeNode of TreeNode.preorder(this)) { + const d = treeNode.depth; + const prefix = d > 0 ? '│ '.repeat(d - 1) + '└── ' : ''; + result += prefix + treeNode.toString({ node, data }) + '\n'; + } + return result; + } +} diff --git a/src/lib/tree-serializer.ts b/src/lib/tree-serializer.ts new file mode 100644 index 0000000..744164b --- /dev/null +++ b/src/lib/tree-serializer.ts @@ -0,0 +1,280 @@ +/** + * These functions serialize and deserialize a TreeNode to/from + * a file or Buffer. The serialized format is JSON, and it can be + * optionally gzipped for smaller size. + * + * See below for usage examples. + * + * File-based, gzipped: + * await serializeTreeToFile({ root, filePath: './myTree.json.gz', compress: true }); + * const tree = deserializeTreeFromFile({ filePath: './myTree.json.gz' }); + * + * Buffer-based, plain JSON: + * const buf = serializeTreeToBuffer({ root, pretty: true }); + * const tree2 = deserializeTreeFromBuffer({ buffer: buf }); + * + * Buffer-based, gzipped: + * const gzBuf = await serializeTreeToBuffer({ root, compress: true }); + * const tree3 = deserializeTreeFromBuffer({ buffer: gzBuf }); + */ +import archiver from 'archiver'; +import fs from 'fs'; +import path from 'path'; +import { pipeline, Readable, Transform } from 'stream'; +import { finished } from 'stream/promises'; +import { promisify } from 'util'; +import zlib from 'zlib'; + +import { TreeNode } from './tree-node'; + +interface SerializedNode { + data: T; + children: SerializedNode[]; +} + +export interface SerializeFileOptions { + /** Root TreeNode to serialize */ + root: TreeNode; + /** Output path (will overwrite) */ + filePath: string; + /** Whether to gzip the JSON before writing */ + compress?: boolean; +} + +export interface DeserializeFileOptions { + /** Path to read from (JSON or .gz) */ + filePath: string; +} + +/* + * Serialize a TreeNode to disk as JSON or gzipped JSON. + */ +export async function serializeTreeToFile({ + root, + filePath, + compress = false, +}: SerializeFileOptions): Promise { + // ensure output folder exists + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + + // create write stream (optionally gzip) + const fileStream = fs.createWriteStream(filePath); + const gzipStream = compress ? zlib.createGzip() : null; + if (gzipStream) gzipStream.pipe(fileStream); + const out = gzipStream ?? fileStream; + + // write the JSON root opening + out.write('{"data":'); + out.write(JSON.stringify(root.data)); + out.write(',"children":['); + + // helper to write a node and its subtree + async function writeNode(node: TreeNode): Promise { + // open this node + out.write('{"data":'); + out.write(JSON.stringify(node.data)); + out.write(',"children":['); + + // write each child (comma-separated) + for (let i = 0; i < node.children.length; i++) { + if (i > 0) out.write(','); + // eslint-disable-next-line no-await-in-loop + await writeNode(node.children[i]); + } + + // close this node + out.write(']}'); + } + + // write top-level children + for (let i = 0; i < root.children.length; i++) { + if (i > 0) out.write(','); + // eslint-disable-next-line no-await-in-loop + await writeNode(root.children[i]); + } + + // close the JSON + out.write(']}'); + + out.end(); + await finished(out); +} + +/* + * Read back a TreeNode from disk, auto-detecting gzip. + */ +export function deserializeTreeFromFile({ + filePath, +}: DeserializeFileOptions): TreeNode { + const buf = fs.readFileSync(filePath); + const isGzipped = buf[0] === 0x1f && buf[1] === 0x8b; + const json = (isGzipped ? zlib.gunzipSync(buf as Uint8Array) : buf).toString( + 'utf8' + ); + + // fallback to full parse—if your JSON is enormous you can + // also hook in a streaming parser like `stream-json` + const parsed = JSON.parse(json) as SerializedNode; + + function build(obj: SerializedNode): TreeNode { + const node = new TreeNode(obj.data); + for (const childObj of obj.children) { + const child = build(childObj); + child.parent = node; + node.children.push(child); + } + return node; + } + + return build(parsed); +} + +export interface BufferSerializeOptions { + /** Root TreeNode to serialize */ + root: TreeNode; + /** Pretty-print JSON (default false) */ + pretty?: boolean; + /** Whether to gzip the JSON before returning */ + compress?: boolean; +} + +export interface BufferDeserializeOptions { + /** Buffer containing JSON or gzipped JSON */ + buffer: Buffer; +} + +/* + * Streamly serialize a TreeNode into a Buffer of JSON or gzipped JSON + * without ever building a giant string in memory. + */ +export async function serializeTreeToBuffer({ + root, + pretty = false, + compress = false, +}: BufferSerializeOptions): Promise { + // Create a Readable that we'll push JSON fragments into + const readable = new Readable({ + read() { + // No-op; we push manually + }, + }); + + // Helper to push JSON fragments + const push = (chunk: string): boolean => readable.push(chunk, 'utf8'); + + // Start the JSON document + push('{"data":'); + push(pretty ? JSON.stringify(root.data, null, 2) : JSON.stringify(root.data)); + push(',"children":['); + + // Recursive writer + const writeNode = (node: TreeNode): void => { + push(pretty ? '\n{' : '{'); + push('"data":'); + push( + pretty ? JSON.stringify(node.data, null, 2) : JSON.stringify(node.data) + ); + push(',"children":['); + node.children.forEach((child, idx) => { + if (idx > 0) push(','); + writeNode(child); + }); + push(']'); + push('}'); + }; + + // Write top-level children + root.children.forEach((child, idx) => { + if (idx > 0) push(','); + writeNode(child); + }); + + // Close document + push(']'); + push('}'); + readable.push(null); + + // Choose gzip or pass-through + const transform = compress + ? zlib.createGzip() + : new Transform({ + transform(chunk, _enc, callback) { + callback(null, chunk); + }, + }); + + // Collector for Buffer chunks + const chunks: Buffer[] = []; + const collector = new Transform({ + transform(chunk, _enc, callback) { + chunks.push(Buffer.from(chunk)); + callback(); + }, + }); + + // Pipeline: readable -> transform -> collector + const pipeAsync = promisify(pipeline); + await pipeAsync(readable, transform, collector); + + // Combine all chunks into one Buffer + return Buffer.concat(chunks as Uint8Array[]); +} + +/* + * Deserialize a TreeNode from a Buffer of JSON or gzipped JSON. + */ +export function deserializeTreeFromBuffer({ + buffer, +}: BufferDeserializeOptions): TreeNode { + // Detect gzip by magic numbers + const isGz = buffer[0] === 0x1f && buffer[1] === 0x8b; + const dataBuf = isGz ? zlib.gunzipSync(buffer as Uint8Array) : buffer; + const parsed = JSON.parse(dataBuf.toString('utf8')) as SerializedNode; + + // Rebuild TreeNode + const build = (obj: SerializedNode): TreeNode => { + const node = new TreeNode(obj.data); + for (const childObj of obj.children) { + const child = build(childObj); + child.parent = node; + node.children.push(child); + } + return node; + }; + + return build(parsed); +} + +export interface SerializeZipFileOptions { + /** Root TreeNode to serialize */ + root: TreeNode; + /** Output .zip file path (will overwrite) */ + filePath: string; + /** Name of the JSON entry inside the zip (e.g. "my-tree.json") */ + entryName: string; +} + +/* + * Serialize a TreeNode into a ZIP file containing a single JSON entry. + */ +export async function serializeTreeToZipFile({ + root, + filePath, + entryName, +}: SerializeZipFileOptions): Promise { + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + + const jsonBuffer = await serializeTreeToBuffer({ root }); + + await new Promise((resolve, reject) => { + const fileStream = fs.createWriteStream(filePath); + const archive = archiver('zip'); + + fileStream.on('close', resolve); + archive.on('error', reject); + + archive.pipe(fileStream); + archive.append(jsonBuffer, { name: entryName }); + archive.finalize().catch(reject); + }); +} diff --git a/test/commands/scene-trees/export.test.ts b/test/commands/scene-trees/export.test.ts new file mode 100644 index 0000000..a0e67d8 --- /dev/null +++ b/test/commands/scene-trees/export.test.ts @@ -0,0 +1,70 @@ +import { IConfig } from '@oclif/config'; +import { expect, test } from '@oclif/test'; +import { SceneItemData, VertexClient } from '@vertexvis/api-client-node'; +import sinon, { assert } from 'sinon'; + +import Export from '../../../src/commands/scene-trees/export'; +import * as vc from '../../../src/lib/client'; +import * as si from '../../../src/lib/scene-items'; +import * as ts from '../../../src/lib/tree-serializer'; +import { TreeNode } from '../../../src/lib/tree-node'; + +const sceneId = 'my-scene-id'; + +describe('scene-trees:export', () => { + afterEach(() => { + sinon.restore(); + }); + + test + .command(['scene-trees:export']) + .catch((error) => { + expect(error.message).to.contain('Missing 1 required arg:'); + expect(error.message).to.contain('sceneId'); + }) + .it('requires sceneId'); + + test + .stdout() + .do(async () => { + sinon + .stub(vc, 'vertexClient') + .resolves(sinon.stub() as unknown as VertexClient); + + const root = new TreeNode( + { id: 'root-id' } as SceneItemData + ); + sinon.stub(si, 'fetchSceneItemTree').resolves(root); + sinon.stub(ts, 'serializeTreeToZipFile').resolves(); + + await new Export([sceneId], {} as IConfig).run(); + }) + .it('saves tree to default zip path', (ctx) => { + expect(ctx.stdout).to.contain(`${sceneId}.zip`); + }); + + test + .stdout() + .do(async () => { + sinon + .stub(vc, 'vertexClient') + .resolves(sinon.stub() as unknown as VertexClient); + + const root = new TreeNode( + { id: 'root-id' } as SceneItemData + ); + sinon.stub(si, 'fetchSceneItemTree').resolves(root); + const serializeStub = sinon.stub(ts, 'serializeTreeToZipFile').resolves(); + + await new Export([sceneId, '--output', 'custom.zip'], {} as IConfig).run(); + + assert.calledOnce(serializeStub); + expect(serializeStub.getCall(0).args[0].filePath).to.equal('custom.zip'); + expect(serializeStub.getCall(0).args[0].entryName).to.equal( + `${sceneId}.json` + ); + }) + .it('uses --output path and correct entry name', (ctx) => { + expect(ctx.stdout).to.contain('custom.zip'); + }); +}); diff --git a/test/commands/scene-trees/view.test.ts b/test/commands/scene-trees/view.test.ts new file mode 100644 index 0000000..3f78991 --- /dev/null +++ b/test/commands/scene-trees/view.test.ts @@ -0,0 +1,44 @@ +import { IConfig } from '@oclif/config'; +import { expect, test } from '@oclif/test'; +import { SceneItemData, VertexClient } from '@vertexvis/api-client-node'; +import sinon from 'sinon'; + +import View from '../../../src/commands/scene-trees/view'; +import * as vc from '../../../src/lib/client'; +import * as si from '../../../src/lib/scene-items'; +import { TreeNode } from '../../../src/lib/tree-node'; + +const sceneId = 'my-scene-id'; + +describe('scene-trees:view', () => { + afterEach(() => { + sinon.restore(); + }); + + test + .command(['scene-trees:view']) + .catch((error) => { + expect(error.message).to.contain('Missing 1 required arg:'); + expect(error.message).to.contain('sceneId'); + }) + .it('requires sceneId'); + + test + .stdout() + .do(async () => { + sinon + .stub(vc, 'vertexClient') + .resolves(sinon.stub() as unknown as VertexClient); + + const root = new TreeNode( + { id: 'root-id' } as SceneItemData + ); + new TreeNode({ id: 'child-id' } as SceneItemData, root); + sinon.stub(si, 'fetchSceneItemTree').resolves(root); + + await new View([sceneId], {} as IConfig).run(); + }) + .it('outputs the tree dump', (ctx) => { + expect(ctx.stdout).to.contain('[TreeNode'); + }); +}); diff --git a/yarn.lock b/yarn.lock index 60490dd..64fbef0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -240,6 +240,18 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -477,6 +489,11 @@ dependencies: fancy-test "^1.4.10" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3": version "1.8.3" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" @@ -532,6 +549,13 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== +"@types/archiver@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-7.0.0.tgz#475d5aa4076ffc05f2c78dc7540b0ea4ab8c7d7a" + integrity sha512-/3vwGwx9n+mCQdYZ2IKGGHEFL30I96UgBlk8EtRDDFQ9uxM1l4O5Ci6r00EMAkiDaTqD9DQ6nVrWRICnBPtzzg== + dependencies: + "@types/readdir-glob" "*" + "@types/chai@*", "@types/chai@^4.3": version "4.3.0" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" @@ -582,6 +606,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.26.tgz#63d204d136c9916fb4dcd1b50f9740fe86884e47" integrity sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ== +"@types/readdir-glob@*": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@types/readdir-glob/-/readdir-glob-1.1.5.tgz#21a4a98898fc606cb568ad815f2a0eedc24d412a" + integrity sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg== + dependencies: + "@types/node" "*" + "@types/sinon@*": version "10.0.11" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.11.tgz#8245827b05d3fc57a6601bd35aee1f7ad330fc42" @@ -697,6 +728,13 @@ eslint-plugin-prettier "^4.0.0" prettier "^2.4.1" +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -767,6 +805,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -781,6 +824,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^4.2.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" @@ -801,6 +849,32 @@ append-transform@^2.0.0: dependencies: default-require-extensions "^3.0.0" +archiver-utils@^5.0.0, archiver-utils@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-5.0.2.tgz#63bc719d951803efc72cf961a56ef810760dd14d" + integrity sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA== + dependencies: + glob "^10.0.0" + graceful-fs "^4.2.0" + is-stream "^2.0.1" + lazystream "^1.0.0" + lodash "^4.17.15" + normalize-path "^3.0.0" + readable-stream "^4.0.0" + +archiver@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-7.0.1.tgz#c9d91c350362040b8927379c7aa69c0655122f61" + integrity sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ== + dependencies: + archiver-utils "^5.0.2" + async "^3.2.4" + buffer-crc32 "^1.0.0" + readable-stream "^4.0.0" + readdir-glob "^1.1.2" + tar-stream "^3.0.0" + zip-stream "^6.0.1" + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -838,6 +912,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async@^3.2.4: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -852,11 +931,21 @@ axios@^1.6.4: form-data "^4.0.0" proxy-from-env "^1.1.0" +b4a@^1.6.4: + version "1.7.5" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.7.5.tgz#573e93bf2664de8779069ef736615c1c63ec1b74" + integrity sha512-iEsKNwDh1wiWTps1/hdkNdmBgDlDVZP5U57ZVOlt+dNFqpc/lpPouCIxZw+DYBgc4P9NDfIZMPNR4CHNhzwLIA== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +bare-events@^2.7.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.2.tgz#7b3e10bd8e1fc80daf38bb516921678f566ab89f" + integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -914,6 +1003,11 @@ browserslist@^4.17.5: node-releases "^2.0.2" picocolors "^1.0.0" +buffer-crc32@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-1.0.0.tgz#a10993b9055081d55304bd9feb4a072de179f405" + integrity sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -927,6 +1021,14 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + caching-transform@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" @@ -1132,6 +1234,17 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= +compress-commons@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-6.0.2.tgz#26d31251a66b9d6ba23a84064ecd3a6a71d2609e" + integrity sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg== + dependencies: + crc-32 "^1.2.0" + crc32-stream "^6.0.0" + is-stream "^2.0.1" + normalize-path "^3.0.0" + readable-stream "^4.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1154,6 +1267,24 @@ convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +crc32-stream@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-6.0.0.tgz#8529a3868f8b27abb915f6c3617c0fadedbf9430" + integrity sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g== + dependencies: + crc-32 "^1.2.0" + readable-stream "^4.0.0" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1179,6 +1310,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + debug@4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" @@ -1256,6 +1396,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + electron-to-chromium@^1.4.84: version "1.4.103" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.103.tgz#abfe376a4d70fa1e1b4b353b95df5d6dfd05da3a" @@ -1266,6 +1411,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -1581,6 +1731,23 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events-universal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/events-universal/-/events-universal-1.0.1.tgz#b56a84fd611b6610e0a2d0f09f80fdf931e2dfe6" + integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== + dependencies: + bare-events "^2.7.0" + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" @@ -1623,6 +1790,11 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +fast-fifo@^1.2.0, fast-fifo@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" + integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== + fast-glob@^3.0.3, fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" @@ -1735,6 +1907,14 @@ foreground-child@^2.0.0: cross-spawn "^7.0.0" signal-exit "^3.0.2" +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -1857,6 +2037,18 @@ glob@7.2.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.0.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" + integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -1964,7 +2156,7 @@ hyperlinker@^1.0.0: resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -2010,7 +2202,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@^2.0.4: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2076,7 +2268,7 @@ is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= -is-stream@^2.0.0: +is-stream@^2.0.0, is-stream@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== @@ -2108,6 +2300,11 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2174,6 +2371,15 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2260,6 +2466,13 @@ just-extend@^4.0.2: resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744" integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg== +lazystream@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" + integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== + dependencies: + readable-stream "^2.0.5" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2352,6 +2565,11 @@ lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +lodash@^4.17.15: + version "4.17.23" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" + integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== + log-symbols@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" @@ -2367,6 +2585,11 @@ loupe@^2.3.1: dependencies: get-func-name "^2.0.0" +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2442,6 +2665,25 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^5.1.0: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" + integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== + mkdirp-classic@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" @@ -2679,6 +2921,11 @@ package-hash@^4.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2737,6 +2984,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" @@ -2788,6 +3043,11 @@ prettier@^2.4.1, prettier@^2.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + process-on-spawn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" @@ -2795,6 +3055,11 @@ process-on-spawn@^1.0.0: dependencies: fromentries "^1.2.0" +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -2864,6 +3129,19 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +readable-stream@^2.0.5: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -2873,6 +3151,24 @@ readable-stream@^3.1.1, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.0.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readdir-glob@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" + integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== + dependencies: + minimatch "^5.1.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -2974,7 +3270,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.1: +safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -3053,6 +3349,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sinon@^12.0: version "12.0.1" resolved "https://registry.yarnpkg.com/sinon/-/sinon-12.0.1.tgz#331eef87298752e1b88a662b699f98e403c859e9" @@ -3155,6 +3456,24 @@ stdout-stderr@^0.1.9: debug "^4.1.1" strip-ansi "^6.0.0" +streamx@^2.15.0: + version "2.23.0" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.23.0.tgz#7d0f3d00d4a6c5de5728aecd6422b4008d66fd0b" + integrity sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg== + dependencies: + events-universal "^1.0.0" + fast-fifo "^1.3.2" + text-decoder "^1.1.0" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -3164,13 +3483,36 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2 is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string_decoder@^1.1.1: +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -3178,6 +3520,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" @@ -3264,6 +3613,15 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" +tar-stream@^3.0.0: + version "3.1.7" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" + integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== + dependencies: + b4a "^1.6.4" + fast-fifo "^1.2.0" + streamx "^2.15.0" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -3273,6 +3631,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-decoder@^1.1.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.7.tgz#5d073a9a74b9c0a9d28dfadcab96b604af57d8ba" + integrity sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ== + dependencies: + b4a "^1.6.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -3427,7 +3792,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@^1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -3501,6 +3866,15 @@ workerpool@6.2.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -3519,6 +3893,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -3628,3 +4011,12 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zip-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-6.0.1.tgz#e141b930ed60ccaf5d7fa9c8260e0d1748a2bbfb" + integrity sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA== + dependencies: + archiver-utils "^5.0.0" + compress-commons "^6.0.2" + readable-stream "^4.0.0" From d55ec0ee461e736ad9f29d07eb567fcdf9559766 Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Thu, 19 Feb 2026 13:27:48 -0600 Subject: [PATCH 2/6] Updated dependencies --- yarn.lock | 508 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 305 insertions(+), 203 deletions(-) diff --git a/yarn.lock b/yarn.lock index 64fbef0..4bf44fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -199,17 +199,12 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@cspotcode/source-map-consumer@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" - integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== - -"@cspotcode/source-map-support@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" - integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== dependencies: - "@cspotcode/source-map-consumer" "0.8.0" + "@jridgewell/trace-mapping" "0.3.9" "@eslint/eslintrc@^0.4.3": version "0.4.3" @@ -285,6 +280,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.0": version "0.3.4" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" @@ -314,7 +317,19 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@oclif/command@^1", "@oclif/command@^1.8.14", "@oclif/command@^1.8.15": +"@oclif/command@^1": + version "1.8.36" + resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.36.tgz#9739b9c268580d064a50887c4597d1b4e86ca8b5" + integrity sha512-/zACSgaYGtAQRzc7HjzrlIs14FuEYAZrMOEwicRoUnZVyRunG4+t5iSEeQu0Xy2bgbCD0U1SP/EdeNZSTXRwjQ== + dependencies: + "@oclif/config" "^1.18.2" + "@oclif/errors" "^1.3.6" + "@oclif/help" "^1.0.1" + "@oclif/parser" "^3.8.17" + debug "^4.1.1" + semver "^7.5.4" + +"@oclif/command@^1.8.14", "@oclif/command@^1.8.15": version "1.8.16" resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.8.16.tgz#bea46f81b2061b47e1cda318a0b923e62ca4cc0c" integrity sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w== @@ -326,6 +341,18 @@ debug "^4.1.1" semver "^7.3.2" +"@oclif/config@1.18.16": + version "1.18.16" + resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.16.tgz#3235d260ab1eb8388ebb6255bca3dd956249d796" + integrity sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA== + dependencies: + "@oclif/errors" "^1.3.6" + "@oclif/parser" "^3.8.16" + debug "^4.3.4" + globby "^11.1.0" + is-wsl "^2.1.1" + tslib "^2.6.1" + "@oclif/config@1.18.2": version "1.18.2" resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.2.tgz#5bfe74a9ba6a8ca3dceb314a81bd9ce2e15ebbfe" @@ -338,29 +365,17 @@ is-wsl "^2.1.1" tslib "^2.0.0" -"@oclif/config@^1.18.2": - version "1.18.3" - resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.3.tgz#ddfc144fdab66b1658c2f1b3478fa7fbfd317e79" - integrity sha512-sBpko86IrTscc39EvHUhL+c++81BVTsIZ3ETu/vG+cCdi0N6vb2DoahR67A9FI2CGnxRRHjnTfa3m6LulwNATA== - dependencies: - "@oclif/errors" "^1.3.5" - "@oclif/parser" "^3.8.0" - debug "^4.1.1" - globby "^11.0.1" - is-wsl "^2.1.1" - tslib "^2.3.1" - -"@oclif/config@^1.18.9": - version "1.18.10" - resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.10.tgz#c0f6c2045abff6381689eb01bf2ffe742a8fb793" - integrity sha512-SjDtdeQwUnHh5rjqqRaBVH6JrBjxtZlHoIwiosOTFcxooLJhW+qcJ/VFOyYw2h/7Jfl95lSKYq+xnMW4aJZd9w== +"@oclif/config@^1.18.2", "@oclif/config@^1.18.9": + version "1.18.17" + resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.18.17.tgz#00aa4049da27edca8f06fc106832d9f0f38786a5" + integrity sha512-k77qyeUvjU8qAJ3XK3fr/QVAqsZO8QOBuESnfeM5HHtPNLSyfVcwiMM2zveSW5xRdLSG3MfV8QnLVkuyCL2ENg== dependencies: "@oclif/errors" "^1.3.6" - "@oclif/parser" "^3.8.12" + "@oclif/parser" "^3.8.17" debug "^4.3.4" globby "^11.1.0" is-wsl "^2.1.1" - tslib "^2.5.0" + tslib "^2.6.1" "@oclif/dev-cli@^1": version "1.26.10" @@ -381,7 +396,7 @@ qqjs "^0.3.10" tslib "^2.0.3" -"@oclif/errors@1.3.5", "@oclif/errors@^1.3.3", "@oclif/errors@^1.3.5": +"@oclif/errors@1.3.5": version "1.3.5" resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.5.tgz#a1e9694dbeccab10fe2fe15acb7113991bed636c" integrity sha512-OivucXPH/eLLlOT7FkCMoZXiaVYf8I/w1eTAM1+gKzfhALwWTusxEx7wBmW0uzvkSg/9ovWLycPaBgJbM3LOCQ== @@ -392,7 +407,7 @@ strip-ansi "^6.0.0" wrap-ansi "^7.0.0" -"@oclif/errors@^1.3.6": +"@oclif/errors@1.3.6", "@oclif/errors@^1.3.3", "@oclif/errors@^1.3.5", "@oclif/errors@^1.3.6": version "1.3.6" resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.3.6.tgz#e8fe1fc12346cb77c4f274e26891964f5175f75d" integrity sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ== @@ -403,7 +418,7 @@ strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -"@oclif/help@^1.0.0", "@oclif/help@^1.0.1": +"@oclif/help@^1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/@oclif/help/-/help-1.0.1.tgz#fd96a3dd9fb2314479e6c8584c91b63754a7dff5" integrity sha512-8rsl4RHL5+vBUAKBL6PFI3mj58hjPCp2VYyXD4TAa7IMStikFfOH2gtWmqLzIlxAED2EpD0dfYwo9JJxYsH7Aw== @@ -418,30 +433,35 @@ widest-line "^3.1.0" wrap-ansi "^6.2.0" +"@oclif/help@^1.0.1": + version "1.0.15" + resolved "https://registry.yarnpkg.com/@oclif/help/-/help-1.0.15.tgz#5e36e576b8132a4906d2662204ad9de7ece87e8f" + integrity sha512-Yt8UHoetk/XqohYX76DfdrUYLsPKMc5pgkzsZVHDyBSkLiGRzujVaGZdjr32ckVZU9q3a47IjhWxhip7Dz5W/g== + dependencies: + "@oclif/config" "1.18.16" + "@oclif/errors" "1.3.6" + chalk "^4.1.2" + indent-string "^4.0.0" + lodash "^4.17.21" + string-width "^4.2.0" + strip-ansi "^6.0.0" + widest-line "^3.1.0" + wrap-ansi "^6.2.0" + "@oclif/linewrap@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== -"@oclif/parser@^3.8", "@oclif/parser@^3.8.0", "@oclif/parser@^3.8.6": - version "3.8.7" - resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.7.tgz#236d48db05d0b00157d3b42d31f9dac7550d2a7c" - integrity sha512-b11xBmIUK+LuuwVGJpFs4LwQN2xj2cBWj2c4z1FtiXGrJ85h9xV6q+k136Hw0tGg1jQoRXuvuBnqQ7es7vO9/Q== - dependencies: - "@oclif/errors" "^1.3.5" - "@oclif/linewrap" "^1.0.0" - chalk "^4.1.0" - tslib "^2.3.1" - -"@oclif/parser@^3.8.12": - version "3.8.12" - resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.12.tgz#5cfd08178faa48d3c3aee5ede4ca780d740bd257" - integrity sha512-yGUrpddLHdPMJIS5jEd55cEPTIFRZRdx38zz0YdFp17Co4RdZvii2jnrnAoICHhumAoQ3EBxwjGpp88D7Bin4w== +"@oclif/parser@^3.8", "@oclif/parser@^3.8.0", "@oclif/parser@^3.8.16", "@oclif/parser@^3.8.17", "@oclif/parser@^3.8.6": + version "3.8.17" + resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.17.tgz#e1ce0f29b22762d752d9da1c7abd57ad81c56188" + integrity sha512-l04iSd0xoh/16TGVpXb81Gg3z7tlQGrEup16BrVLsZBK6SEYpYHRJZnM32BwZrHI97ZSFfuSwVlzoo6HdsaK8A== dependencies: "@oclif/errors" "^1.3.6" "@oclif/linewrap" "^1.0.0" chalk "^4.1.0" - tslib "^2.5.3" + tslib "^2.6.2" "@oclif/plugin-help@3.2.18": version "3.2.18" @@ -530,24 +550,24 @@ integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== "@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + version "1.0.12" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.12.tgz#be57ceac1e4692b41be9de6be8c32a106636dba4" + integrity sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ== "@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== "@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@types/archiver@^7.0.0": version "7.0.0" @@ -556,11 +576,16 @@ dependencies: "@types/readdir-glob" "*" -"@types/chai@*", "@types/chai@^4.3": +"@types/chai@*": version "4.3.0" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== +"@types/chai@^4.3": + version "4.3.20" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" + integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== + "@types/fs-extra@^9.0": version "9.0.13" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.13.tgz#7594fbae04fe7f1918ce8b3d213f74ff44ac1f45" @@ -577,9 +602,9 @@ "@types/node" "*" "@types/json-schema@^7.0.7": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/lodash@*": version "4.14.181" @@ -592,9 +617,9 @@ integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== "@types/mocha@^9": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" - integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== "@types/node@*": version "17.0.23" @@ -602,9 +627,9 @@ integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== "@types/node@^16": - version "16.11.26" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.26.tgz#63d204d136c9916fb4dcd1b50f9740fe86884e47" - integrity sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ== + version "16.18.126" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.126.tgz#27875faa2926c0f475b39a8bb1e546c0176f8d4b" + integrity sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw== "@types/readdir-glob@*": version "1.1.5" @@ -741,19 +766,21 @@ acorn-jsx@^5.3.1: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + version "8.3.5" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.5.tgz#8a6b8ca8fc5b34685af15dabb44118663c296496" + integrity sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw== + dependencies: + acorn "^8.11.0" acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.4.1: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.11.0, acorn@^8.4.1: + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== aggregate-error@^3.0.0: version "3.1.0" @@ -966,21 +993,28 @@ bl@^4.0.3: readable-stream "^3.4.0" brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" -braces@^3.0.2, braces@~3.0.2: +braces@^3.0.2, braces@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1068,17 +1102,17 @@ cardinal@^2.1.1: redeyed "~2.1.0" chai@^4.3: - version "4.3.6" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" - integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + version "4.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" + integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== dependencies: assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - loupe "^2.3.1" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" pathval "^1.1.1" - type-detect "^4.0.5" + type-detect "^4.1.0" chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" @@ -1097,10 +1131,12 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" chokidar@3.5.3: version "3.5.3" @@ -1248,7 +1284,7 @@ compress-commons@^6.0.2: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== confusing-browser-globals@1.0.10: version "1.0.10" @@ -1326,13 +1362,20 @@ debug@4.3.3: dependencies: ms "2.1.2" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: +debug@^4.0.1, debug@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1343,10 +1386,10 @@ decamelize@^4.0.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== +deep-eql@^4.1.3: + version "4.1.4" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" + integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== dependencies: type-detect "^4.0.0" @@ -1378,9 +1421,9 @@ diff@5.0.0, diff@^5.0.0: integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + version "4.0.4" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.4.tgz#7a6dbfda325f25f07517e9b518f897c08332e07d" + integrity sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ== dir-glob@^3.0.1: version "3.0.1" @@ -1466,9 +1509,9 @@ eslint-ast-utils@^1.0.0: lodash.zip "^4.2.0" eslint-config-oclif-typescript@^1.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/eslint-config-oclif-typescript/-/eslint-config-oclif-typescript-1.0.2.tgz#e0b04e9128220c22bf45df3ba454c76ea6aed6bc" - integrity sha512-QUldSp+y0C7tVT3pVNFUUeN53m2IqiY0VvWQNYt5LJoFcaFvrpEB8G3x17LFFku4jy9bg8d+MbkMG1alPwzm1w== + version "1.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-oclif-typescript/-/eslint-config-oclif-typescript-1.0.3.tgz#0061a810bf8f69571ad3c70368badcc018c3358e" + integrity sha512-TeJKXWBQ3uKMtzgz++UFNWpe1WCx8mfqRuzZy1LirREgRlVv656SkVG4gNZat5rRNIQgfDmTS+YebxK02kfylA== dependencies: "@typescript-eslint/eslint-plugin" "^4.31.2" "@typescript-eslint/parser" "^4.31.2" @@ -1795,7 +1838,7 @@ fast-fifo@^1.2.0, fast-fifo@^1.3.2: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.0.3, fast-glob@^3.2.9: +fast-glob@^3.0.3: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== @@ -1806,6 +1849,17 @@ fast-glob@^3.0.3, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -1824,9 +1878,9 @@ fast-xml-parser@^3.21: strnum "^1.0.4" fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.20.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== dependencies: reusify "^1.0.4" @@ -1837,10 +1891,10 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.0.1, fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -1964,22 +2018,22 @@ fs-extra@^8.1: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" @@ -1991,10 +2045,10 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== get-package-type@^0.1.0: version "0.1.0" @@ -2025,7 +2079,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob@7.2.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: +glob@7.2.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -2049,6 +2103,17 @@ glob@^10.0.0: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -2087,11 +2152,16 @@ globby@^11, globby@^11.0.1, globby@^11.0.3, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: +graceful-fs@^4.1.15, graceful-fs@^4.1.2: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -2108,11 +2178,9 @@ has-flag@^4.0.0: integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" + version "1.0.4" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" + integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== hasha@^5.0.0: version "5.2.2" @@ -2122,6 +2190,13 @@ hasha@^5.0.0: is-stream "^2.0.0" type-fest "^0.8.0" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -2167,9 +2242,9 @@ ignore@^4.0.2, ignore@^4.0.6: integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" @@ -2197,7 +2272,7 @@ indent-string@^4.0.0: inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -2219,7 +2294,14 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-core-module@^2.5.0, is-core-module@^2.8.1: +is-core-module@^2.16.1, is-core-module@^2.8.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-core-module@^2.5.0: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== @@ -2234,7 +2316,7 @@ is-docker@^2.0.0: is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -2441,14 +2523,14 @@ json5@^2.1.2: integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== jsonc-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" - integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz#f2a524b4f7fd11e3d791e559977ad60b98b798b4" + integrity sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ== jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== optionalDependencies: graceful-fs "^4.1.6" @@ -2560,12 +2642,12 @@ lodash.zip@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.zip/-/lodash.zip-4.2.0.tgz#ec6662e4896408ed4ab6c542a3990b72cc080020" integrity sha1-7GZi5IlkCO1KtsVCo5kLcswIACA= -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.21: +lodash@^4.17.11, lodash@^4.17.13: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -lodash@^4.17.15: +lodash@^4.17.15, lodash@^4.17.21: version "4.17.23" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== @@ -2578,12 +2660,12 @@ log-symbols@4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== +loupe@^2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== dependencies: - get-func-name "^2.0.0" + get-func-name "^2.0.1" lru-cache@^10.2.0: version "10.4.3" @@ -2614,17 +2696,17 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -marked@^4.0.12: - version "4.0.12" - resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d" - integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ== +marked@^4.0.16: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.2: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -2632,6 +2714,14 @@ micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" +micromatch@^4.0.4, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -2658,14 +2748,7 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^5.1.0: +minimatch@^5.0.1, minimatch@^5.1.0: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== @@ -2729,7 +2812,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -2967,7 +3050,7 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" @@ -3038,11 +3121,16 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.4.1, prettier@^2.5: +prettier@^2.4.1: version "2.6.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== +prettier@^2.5: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -3225,7 +3313,16 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve@^1.10.1, resolve@^1.8.1: +resolve@^1.10.1: + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== + dependencies: + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^1.8.1: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -3240,9 +3337,9 @@ ret@~0.1.10: integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rimraf@^2.6.3: version "2.7.1" @@ -3287,18 +3384,28 @@ semver@^5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: +semver@^6.1.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.2.1, semver@^7.3.4: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== dependencies: lru-cache "^6.0.0" +semver@^7.3.2, semver@^7.3.5, semver@^7.5.4: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -3663,11 +3770,11 @@ to-regex-range@^5.0.1: is-number "^7.0.0" ts-node@^10.4: - version "10.7.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" - integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== dependencies: - "@cspotcode/source-map-support" "0.7.0" + "@cspotcode/source-map-support" "^0.8.0" "@tsconfig/node10" "^1.0.7" "@tsconfig/node12" "^1.0.7" "@tsconfig/node14" "^1.0.0" @@ -3678,10 +3785,10 @@ ts-node@^10.4: create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" - v8-compile-cache-lib "^3.0.0" + v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tslib@2.8.1: +tslib@2.8.1, tslib@^2.0.0, tslib@^2.6.1, tslib@^2.6.2: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -3691,21 +3798,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.3, tslib@^2.3.1: +tslib@^2.0.3: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== - -tslib@^2.5.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" - integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -3727,11 +3824,16 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8: +type-detect@4.0.8, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-detect@^4.0.0, type-detect@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" + integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -3760,14 +3862,14 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" typedoc@^0.22: - version "0.22.13" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.22.13.tgz#d061f8f0fb7c9d686e48814f245bddeea4564e66" - integrity sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ== + version "0.22.18" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.22.18.tgz#1d000c33b66b88fd8cdfea14a26113a83b7e6591" + integrity sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA== dependencies: - glob "^7.2.0" + glob "^8.0.3" lunr "^2.3.9" - marked "^4.0.12" - minimatch "^5.0.1" + marked "^4.0.16" + minimatch "^5.1.0" shiki "^0.10.1" typescript@4.4.x: @@ -3802,10 +3904,10 @@ uuid@^3.3.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -v8-compile-cache-lib@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" - integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-compile-cache@^2.0.3: version "2.3.0" @@ -3821,9 +3923,9 @@ validate-npm-package-license@^3.0.1: spdx-expression-parse "^3.0.0" vscode-oniguruma@^1.6.1: - version "1.6.2" - resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" - integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== vscode-textmate@5.2.0: version "5.2.0" @@ -3905,7 +4007,7 @@ wrap-ansi@^8.1.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" From 087d42d08c88ed9fe424ebe39324f2774e113840 Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Thu, 19 Feb 2026 13:28:03 -0600 Subject: [PATCH 3/6] Improved test coverage --- test/commands/scene-trees/export.test.ts | 19 +- test/commands/scene-trees/view.test.ts | 7 +- test/lib/scene-items.test.ts | 98 ++++++++++ test/lib/tree-builder.test.ts | 127 ++++++++++++ test/lib/tree-node.test.ts | 233 +++++++++++++++++++++++ 5 files changed, 473 insertions(+), 11 deletions(-) create mode 100644 test/lib/scene-items.test.ts create mode 100644 test/lib/tree-builder.test.ts create mode 100644 test/lib/tree-node.test.ts diff --git a/test/commands/scene-trees/export.test.ts b/test/commands/scene-trees/export.test.ts index a0e67d8..068e2a4 100644 --- a/test/commands/scene-trees/export.test.ts +++ b/test/commands/scene-trees/export.test.ts @@ -6,8 +6,8 @@ import sinon, { assert } from 'sinon'; import Export from '../../../src/commands/scene-trees/export'; import * as vc from '../../../src/lib/client'; import * as si from '../../../src/lib/scene-items'; -import * as ts from '../../../src/lib/tree-serializer'; import { TreeNode } from '../../../src/lib/tree-node'; +import * as ts from '../../../src/lib/tree-serializer'; const sceneId = 'my-scene-id'; @@ -31,9 +31,9 @@ describe('scene-trees:export', () => { .stub(vc, 'vertexClient') .resolves(sinon.stub() as unknown as VertexClient); - const root = new TreeNode( - { id: 'root-id' } as SceneItemData - ); + const root = new TreeNode({ + id: 'root-id', + } as SceneItemData); sinon.stub(si, 'fetchSceneItemTree').resolves(root); sinon.stub(ts, 'serializeTreeToZipFile').resolves(); @@ -50,13 +50,16 @@ describe('scene-trees:export', () => { .stub(vc, 'vertexClient') .resolves(sinon.stub() as unknown as VertexClient); - const root = new TreeNode( - { id: 'root-id' } as SceneItemData - ); + const root = new TreeNode({ + id: 'root-id', + } as SceneItemData); sinon.stub(si, 'fetchSceneItemTree').resolves(root); const serializeStub = sinon.stub(ts, 'serializeTreeToZipFile').resolves(); - await new Export([sceneId, '--output', 'custom.zip'], {} as IConfig).run(); + await new Export( + [sceneId, '--output', 'custom.zip'], + {} as IConfig + ).run(); assert.calledOnce(serializeStub); expect(serializeStub.getCall(0).args[0].filePath).to.equal('custom.zip'); diff --git a/test/commands/scene-trees/view.test.ts b/test/commands/scene-trees/view.test.ts index 3f78991..fc09c46 100644 --- a/test/commands/scene-trees/view.test.ts +++ b/test/commands/scene-trees/view.test.ts @@ -30,9 +30,10 @@ describe('scene-trees:view', () => { .stub(vc, 'vertexClient') .resolves(sinon.stub() as unknown as VertexClient); - const root = new TreeNode( - { id: 'root-id' } as SceneItemData - ); + const root = new TreeNode({ + id: 'root-id', + } as SceneItemData); + // eslint-disable-next-line no-new new TreeNode({ id: 'child-id' } as SceneItemData, root); sinon.stub(si, 'fetchSceneItemTree').resolves(root); diff --git a/test/lib/scene-items.test.ts b/test/lib/scene-items.test.ts new file mode 100644 index 0000000..529b591 --- /dev/null +++ b/test/lib/scene-items.test.ts @@ -0,0 +1,98 @@ +import { SceneItemData, VertexClient } from '@vertexvis/api-client-node'; +import { expect } from 'chai'; +import sinon from 'sinon'; + +import { + fetchAllSceneItemsForScene, + fetchSceneItemTree, +} from '../../src/lib/scene-items'; + +const makeItem = (id: string, parentId?: string): SceneItemData => + ({ + id, + relationships: { + parent: parentId + ? { data: { id: parentId, type: 'scene-item' } } + : undefined, + }, + } as unknown as SceneItemData); + +/* + * Build a mock VertexClient whose sceneItems.getSceneItems returns a paginated + * Axios-style response. getPage calls getListing() and reads .data from it, + * so we return { data: { data: items, links: { next: nextHref } } }. + */ +function makeClient( + pages: { items: SceneItemData[]; nextHref?: string }[] +): VertexClient { + let callCount = 0; + const getSceneItems = sinon.stub().callsFake(() => { + const page = pages[callCount] ?? pages[pages.length - 1]; + callCount++; + return Promise.resolve({ + data: { + data: page.items, + links: page.nextHref ? { next: { href: page.nextHref } } : {}, + }, + }); + }); + return { sceneItems: { getSceneItems } } as unknown as VertexClient; +} + +describe('scene-items', () => { + afterEach(() => { + sinon.restore(); + }); + + describe('fetchAllSceneItemsForScene', () => { + it('returns all items from a single page', async () => { + const items = [makeItem('1'), makeItem('2')]; + const client = makeClient([{ items }]); + + const result = await fetchAllSceneItemsForScene(client, 'scene-id'); + expect(result).to.deep.equal(items); + }); + + it('fetches multiple pages until cursor is exhausted', async () => { + const page1 = [makeItem('1')]; + const page2 = [makeItem('2')]; + const client = makeClient([ + { + items: page1, + nextHref: 'https://api.example.com?page[cursor]=next-token', + }, + { items: page2 }, + ]); + + const result = await fetchAllSceneItemsForScene(client, 'scene-id'); + expect(result).to.have.length(2); + }); + + it('returns an empty array when the page has no items', async () => { + const client = makeClient([{ items: [] }]); + + const result = await fetchAllSceneItemsForScene(client, 'scene-id'); + expect(result).to.deep.equal([]); + }); + }); + + describe('fetchSceneItemTree', () => { + it('returns the root node of the scene item tree', async () => { + const items = [makeItem('1'), makeItem('2', '1')]; + const client = makeClient([{ items }]); + + const root = await fetchSceneItemTree(client, 'scene-id'); + expect(root.data?.id).to.equal('1'); + expect(root.children).to.have.length(1); + expect(root.children[0].data?.id).to.equal('2'); + }); + + it('sets parent references correctly on the tree', async () => { + const items = [makeItem('1'), makeItem('2', '1')]; + const client = makeClient([{ items }]); + + const root = await fetchSceneItemTree(client, 'scene-id'); + expect(root.children[0].parent).to.equal(root); + }); + }); +}); diff --git a/test/lib/tree-builder.test.ts b/test/lib/tree-builder.test.ts new file mode 100644 index 0000000..625a556 --- /dev/null +++ b/test/lib/tree-builder.test.ts @@ -0,0 +1,127 @@ +import { expect } from 'chai'; + +import { + buildTreeFromFlat, + buildTreeFromNested, +} from '../../src/lib/tree-builder'; + +interface Item { + id: string; + parentId?: string; + name: string; + children?: Item[]; +} + +describe('tree-builder', () => { + describe('buildTreeFromNested', () => { + it('builds a single node from a leaf record', () => { + const root = buildTreeFromNested({ id: '1', name: 'root' }); + expect(root.data?.id).to.equal('1'); + expect(root.children).to.have.length(0); + expect(root.isRoot()).to.be.true; + }); + + it('builds nested children', () => { + const data: Item = { + id: '1', + name: 'root', + children: [ + { id: '2', name: 'child1', children: [] }, + { id: '3', name: 'child2', children: [] }, + ], + }; + const root = buildTreeFromNested(data); + expect(root.children).to.have.length(2); + expect(root.children[0].data?.id).to.equal('2'); + expect(root.children[1].data?.id).to.equal('3'); + }); + + it('links parents correctly', () => { + const data: Item = { + id: '1', + name: 'root', + children: [{ id: '2', name: 'child', children: [] }], + }; + const root = buildTreeFromNested(data); + expect(root.children[0].parent).to.equal(root); + }); + + it('builds deeply nested trees', () => { + const data: Item = { + id: '1', + name: 'root', + children: [ + { + id: '2', + name: 'child', + children: [{ id: '3', name: 'grandchild', children: [] }], + }, + ], + }; + const root = buildTreeFromNested(data); + expect(root.size).to.equal(3); + expect(root.children[0].children[0].data?.id).to.equal('3'); + expect(root.children[0].children[0].depth).to.equal(2); + }); + }); + + describe('buildTreeFromFlat', () => { + const records: Item[] = [ + { id: '1', parentId: undefined, name: 'Root' }, + { id: '2', parentId: '1', name: 'Child 1' }, + { id: '3', parentId: '1', name: 'Child 2' }, + { id: '4', parentId: '2', name: 'Grandchild 1' }, + ]; + + const idFn = (r: Item): string => r.id; + const parentFn = (r: Item): string | undefined => r.parentId; + + it('returns a single root for a rooted tree', () => { + const roots = buildTreeFromFlat(records, idFn, parentFn); + expect(roots).to.have.length(1); + }); + + it('sets the correct data on the root', () => { + const [root] = buildTreeFromFlat(records, idFn, parentFn); + expect(root.data?.name).to.equal('Root'); + }); + + it('attaches correct children to root', () => { + const [root] = buildTreeFromFlat(records, idFn, parentFn); + expect(root.children).to.have.length(2); + }); + + it('sets parent references on children', () => { + const [root] = buildTreeFromFlat(records, idFn, parentFn); + expect(root.children[0].parent).to.equal(root); + expect(root.children[1].parent).to.equal(root); + }); + + it('places grandchildren at the correct depth', () => { + const [root] = buildTreeFromFlat(records, idFn, parentFn); + const grandchild = root.children[0].children[0]; + expect(grandchild.depth).to.equal(2); + expect(grandchild.data?.name).to.equal('Grandchild 1'); + }); + + it('returns multiple roots for a forest', () => { + const multiRoot: Item[] = [ + { id: '1', name: 'Root A' }, + { id: '2', name: 'Root B' }, + ]; + const roots = buildTreeFromFlat(multiRoot, idFn, parentFn); + expect(roots).to.have.length(2); + }); + + it('treats records with unknown parent ids as roots', () => { + const orphan: Item[] = [{ id: '1', parentId: 'missing', name: 'Orphan' }]; + const roots = buildTreeFromFlat(orphan, idFn, parentFn); + expect(roots).to.have.length(1); + expect(roots[0].parent).to.be.null; + }); + + it('returns an empty array for empty input', () => { + expect(buildTreeFromFlat([], idFn, parentFn)).to.deep.equal([]); + }); + }); +}); diff --git a/test/lib/tree-node.test.ts b/test/lib/tree-node.test.ts new file mode 100644 index 0000000..f1ffcae --- /dev/null +++ b/test/lib/tree-node.test.ts @@ -0,0 +1,233 @@ +import { expect } from 'chai'; + +import { TreeNode } from '../../src/lib/tree-node'; + +describe('TreeNode', () => { + let root: TreeNode; + let child1: TreeNode; + let grandchild: TreeNode; + + beforeEach(() => { + root = new TreeNode('root'); + child1 = new TreeNode('child1', root); + // eslint-disable-next-line no-new + new TreeNode('child2', root); + grandchild = new TreeNode('grandchild', child1); + }); + + describe('constructor', () => { + it('creates a node with null data by default', () => { + const node = new TreeNode(); + expect(node.data).to.be.null; + expect(node.parent).to.be.null; + expect(node.children).to.have.length(0); + }); + + it('links to parent and adds itself to parent children', () => { + expect(child1.parent).to.equal(root); + expect(root.children).to.include(child1); + }); + }); + + describe('size', () => { + it('returns 1 for a leaf', () => { + expect(grandchild.size).to.equal(1); + }); + + it('counts all descendants', () => { + expect(root.size).to.equal(4); + }); + }); + + describe('depth', () => { + it('returns 0 for root', () => { + expect(root.depth).to.equal(0); + }); + + it('returns 1 for a direct child', () => { + expect(child1.depth).to.equal(1); + }); + + it('returns 2 for a grandchild', () => { + expect(grandchild.depth).to.equal(2); + }); + }); + + describe('numChildren', () => { + it('returns 0 for a leaf', () => { + expect(grandchild.numChildren).to.equal(0); + }); + + it('returns the correct child count', () => { + expect(root.numChildren).to.equal(2); + }); + }); + + describe('numSiblings', () => { + it('returns 0 for root', () => { + expect(root.numSiblings).to.equal(0); + }); + + it('returns sibling count including self', () => { + expect(child1.numSiblings).to.equal(2); + }); + + it('returns 1 for an only child', () => { + expect(grandchild.numSiblings).to.equal(1); + }); + }); + + describe('isRoot', () => { + it('returns true for root', () => { + expect(root.isRoot()).to.be.true; + }); + + it('returns false for non-root', () => { + expect(child1.isRoot()).to.be.false; + }); + }); + + describe('isLeaf', () => { + it('returns true for a leaf', () => { + expect(grandchild.isLeaf()).to.be.true; + }); + + it('returns false for a non-leaf', () => { + expect(root.isLeaf()).to.be.false; + }); + }); + + describe('hasChildren', () => { + it('returns true when node has children', () => { + expect(root.hasChildren()).to.be.true; + }); + + it('returns false for a leaf', () => { + expect(grandchild.hasChildren()).to.be.false; + }); + }); + + describe('hasSiblings', () => { + it('returns false for root', () => { + expect(root.hasSiblings()).to.be.false; + }); + + it('returns true when node has siblings', () => { + expect(child1.hasSiblings()).to.be.true; + }); + + it('returns false for an only child', () => { + expect(grandchild.hasSiblings()).to.be.false; + }); + }); + + describe('isEmpty', () => { + it('returns true for a leaf', () => { + expect(grandchild.isEmpty()).to.be.true; + }); + + it('returns false when node has children', () => { + expect(root.isEmpty()).to.be.false; + }); + }); + + describe('preorder', () => { + it('yields nodes in pre-order', () => { + const nodes = [...TreeNode.preorder(root)].map((n) => n.data); + expect(nodes).to.deep.equal(['root', 'child1', 'grandchild', 'child2']); + }); + }); + + describe('[Symbol.iterator]', () => { + it('iterates nodes in pre-order', () => { + const data = [...root].map((n) => n.data); + expect(data).to.deep.equal(['root', 'child1', 'grandchild', 'child2']); + }); + }); + + describe('contains', () => { + it('returns true when the value exists in the subtree', () => { + expect(root.contains('grandchild')).to.be.true; + }); + + it('returns false when the value does not exist', () => { + expect(root.contains('missing')).to.be.false; + }); + }); + + describe('clear', () => { + it('removes all descendants', () => { + root.clear(); + expect(root.children).to.have.length(0); + expect(root.size).to.equal(1); + }); + + it('recursively clears nested children', () => { + root.clear(); + expect(child1.children).to.have.length(0); + }); + }); + + describe('toArray', () => { + it('returns data payloads in pre-order', () => { + expect(root.toArray()).to.deep.equal([ + 'root', + 'child1', + 'grandchild', + 'child2', + ]); + }); + }); + + describe('toString', () => { + it('includes [TreeNode in the output', () => { + expect(root.toString()).to.contain('[TreeNode'); + }); + + it('marks root with (root)', () => { + expect(root.toString()).to.contain('(root)'); + }); + + it('marks leaves with (leaf)', () => { + expect(grandchild.toString()).to.contain('(leaf)'); + }); + + it('shows singular "child node" for exactly one child', () => { + expect(child1.toString()).to.contain('1 child node'); + }); + + it('shows plural "child nodes" for multiple children', () => { + expect(root.toString()).to.contain('2 child nodes'); + }); + + it('uses custom node formatter when provided', () => { + expect(root.toString({ node: (n) => `id:${n.data}` })).to.equal( + 'id:root' + ); + }); + + it('uses custom data formatter when provided', () => { + expect(root.toString({ data: (d) => `<${d}>` })).to.contain(''); + }); + }); + + describe('dump', () => { + it('returns a multiline string containing all nodes', () => { + const out = root.dump(); + expect(out).to.contain('root'); + expect(out).to.contain('child1'); + expect(out).to.contain('grandchild'); + expect(out).to.contain('child2'); + }); + + it('includes tree prefix characters for children', () => { + expect(root.dump()).to.contain('└──'); + }); + + it('accepts custom node and data formatters', () => { + const out = root.dump({ data: (d) => `[${d}]` }); + expect(out).to.contain('[root]'); + expect(out).to.contain('[child1]'); + }); + }); +}); From cbc84445905e2528a657160d80bdec8437a4b826 Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Thu, 19 Feb 2026 14:23:48 -0600 Subject: [PATCH 4/6] Made all public static properties readonly per sonar --- src/commands/configure.ts | 6 +++--- src/commands/create-items.ts | 8 ++++---- src/commands/create-parts.ts | 8 ++++---- src/commands/create-scene.ts | 8 ++++---- src/commands/exports/create.ts | 6 +++--- src/commands/exports/download.ts | 8 ++++---- src/commands/exports/get.ts | 8 ++++---- src/commands/files/delete.ts | 8 ++++---- src/commands/files/get.ts | 8 ++++---- src/commands/files/list.ts | 6 +++--- src/commands/part-revisions/render.ts | 8 ++++---- src/commands/parts/delete.ts | 8 ++++---- src/commands/parts/get.ts | 8 ++++---- src/commands/parts/list.ts | 6 +++--- src/commands/scene-items/get.ts | 8 ++++---- src/commands/scene-items/list.ts | 6 +++--- src/commands/scene-trees/export.ts | 8 ++++---- src/commands/scene-trees/view.ts | 8 ++++---- src/commands/scene-view-states/delete.ts | 8 ++++---- src/commands/scene-view-states/get.ts | 8 ++++---- src/commands/scene-view-states/list.ts | 6 +++--- src/commands/scene-views/create.ts | 6 +++--- src/commands/scene-views/get.ts | 8 ++++---- src/commands/scene-views/list.ts | 6 +++--- src/commands/scene-views/render.ts | 8 ++++---- src/commands/scenes/delete.ts | 8 ++++---- src/commands/scenes/get.ts | 8 ++++---- src/commands/scenes/list.ts | 6 +++--- src/commands/scenes/render.ts | 8 ++++---- src/commands/stream-keys/create.ts | 6 +++--- src/commands/webhook-subscriptions/create.ts | 6 +++--- src/lib/base-delete.ts | 2 +- src/lib/base-get.ts | 2 +- src/lib/base-list.ts | 2 +- src/lib/base-render.ts | 2 +- src/lib/base.ts | 2 +- 36 files changed, 118 insertions(+), 118 deletions(-) diff --git a/src/commands/configure.ts b/src/commands/configure.ts index cf5dffc..ce713a1 100644 --- a/src/commands/configure.ts +++ b/src/commands/configure.ts @@ -8,15 +8,15 @@ import { deleteFile, fileExists } from '../lib/fs'; const UserRw = 0o600; // rw- --- --- export default class Configure extends BaseCommand { - public static description = `Configure Vertex credentials.`; + public static readonly description = `Configure Vertex credentials.`; - public static examples = [ + public static readonly examples = [ `$ vertex configure Saved 'https://platform.vertexvis.com' configuration to '~/.config/@vertexvis/cli/config.json'. `, ]; - public static flags = { ...BaseCommand.flags }; + public static readonly flags = { ...BaseCommand.flags }; public async run(): Promise { const basePath = this.parsedFlags?.basePath; diff --git a/src/commands/create-items.ts b/src/commands/create-items.ts index 59d53ae..fa11273 100644 --- a/src/commands/create-items.ts +++ b/src/commands/create-items.ts @@ -7,17 +7,17 @@ import BaseCommand from '../lib/base'; import { fileExists } from '../lib/fs'; export default class CreateItems extends BaseCommand { - public static description = `Calculate path IDs and transforms for each instance in file and output JSON file containing SceneItems (as defined in src/create-items/index.d.ts).`; + public static readonly description = `Calculate path IDs and transforms for each instance in file and output JSON file containing SceneItems (as defined in src/create-items/index.d.ts).`; - public static examples = [ + public static readonly examples = [ `$ vertex create-items --format pvs [YOUR_PATH_TO_XML_FILE] Wrote 5 pvs item(s) from '[YOUR_PATH_TO_XML_FILE]' to 'items.json'. `, ]; - public static args = [{ name: 'path' }]; + public static readonly args = [{ name: 'path' }]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, format: flags.string({ char: 'f', diff --git a/src/commands/create-parts.ts b/src/commands/create-parts.ts index 45b951e..03d7c57 100644 --- a/src/commands/create-parts.ts +++ b/src/commands/create-parts.ts @@ -37,17 +37,17 @@ interface Args extends BaseReq { } export default class CreateParts extends BaseCommand { - public static description = `Given JSON file containing SceneItems (as defined in src/create-items/index.d.ts), upload geometry files and create parts in Vertex Part Library.`; + public static readonly description = `Given JSON file containing SceneItems (as defined in src/create-items/index.d.ts), upload geometry files and create parts in Vertex Part Library.`; - public static examples = [ + public static readonly examples = [ `$ vertex create-parts --directory [YOUR_PATH_TO_GEOMETRY_DIRECTORY] [YOUR_PATH_TO_JSON_FILE] ████████████████████████████████████████ 100% | 10/10 `, ]; - public static args = [{ name: 'path' }]; + public static readonly args = [{ name: 'path' }]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, directory: flags.string({ char: 'd', diff --git a/src/commands/create-scene.ts b/src/commands/create-scene.ts index 3beb23b..0d1f283 100644 --- a/src/commands/create-scene.ts +++ b/src/commands/create-scene.ts @@ -27,18 +27,18 @@ type CreateSceneFn = ( ) => Promise; export default class CreateScene extends BaseCommand { - public static description = `Given JSON file containing SceneItems (as defined in src/create-items/index.d.ts), create scene in Vertex.`; + public static readonly description = `Given JSON file containing SceneItems (as defined in src/create-items/index.d.ts), create scene in Vertex.`; - public static examples = [ + public static readonly examples = [ `$ vertex create-scene --name my-scene [YOUR_PATH_TO_JSON_FILE] ████████████████████████████████████████ 100% | 10/10 f79d4760-0b71-44e4-ad0b-22743fdd4ca3 `, ]; - public static args = [{ name: 'path' }]; + public static readonly args = [{ name: 'path' }]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, validate: flags.boolean({ description: diff --git a/src/commands/exports/create.ts b/src/commands/exports/create.ts index 13c09b5..73024d1 100644 --- a/src/commands/exports/create.ts +++ b/src/commands/exports/create.ts @@ -13,15 +13,15 @@ import { vertexClient } from '../../lib/client'; type CreateExportFn = (args: CreateExportReq) => Promise; export default class Create extends BaseCommand { - public static description = `Create an export for a scene.`; + public static readonly description = `Create an export for a scene.`; - public static examples = [ + public static readonly examples = [ `$ vertex exports:create --sceneId f79d4760-0b71-44e4-ad0b-22743fdd4ca3 --format jt bf0c4343-96eb-4aa9-8dee-e79c6458dedf `, ]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, sceneId: flags.string({ description: `Scene to export.`, diff --git a/src/commands/exports/download.ts b/src/commands/exports/download.ts index 0539a25..e8314d3 100644 --- a/src/commands/exports/download.ts +++ b/src/commands/exports/download.ts @@ -5,17 +5,17 @@ import { vertexClient } from '../../lib/client'; import { exportGetter } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Download an export.`; + public static readonly description = `Download an export.`; - public static examples = [ + public static readonly examples = [ `$ vertex exports:download 54964c61-05d8-4f37-9638-18f7c4960c80 Export saved as: 54964c61-05d8-4f37-9638-18f7c4960c80 `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/exports/get.ts b/src/commands/exports/get.ts index 03e2314..2c40d8f 100644 --- a/src/commands/exports/get.ts +++ b/src/commands/exports/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { exportGetter, getterFn } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get an export.`; + public static readonly description = `Get an export.`; - public static examples = [ + public static readonly examples = [ `$ vertex exports:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id DownloadUrl 54964c61-05d8-4f37-9638-18f7c4960c80 https://some-url.com/some-file `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/files/delete.ts b/src/commands/files/delete.ts index 0217f7a..41aa336 100644 --- a/src/commands/files/delete.ts +++ b/src/commands/files/delete.ts @@ -6,18 +6,18 @@ import { vertexClient } from '../../lib/client'; import { deleter, fileDeleter, validate } from '../../lib/deleter'; export default class Delete extends BaseDeleteCommand { - public static description = `Delete files.`; + public static readonly description = `Delete files.`; - public static examples = [ + public static readonly examples = [ `$ vertex files:delete 54964c61-05d8-4f37-9638-18f7c4960c80 Deleted file 54964c61-05d8-4f37-9638-18f7c4960c80. Deleting file(s)...... done `, ]; - public static args = [{ name: 'id' }]; + public static readonly args = [{ name: 'id' }]; - public static flags = BaseDeleteCommand.flags; + public static readonly flags = BaseDeleteCommand.flags; public async run(): Promise { const { diff --git a/src/commands/files/get.ts b/src/commands/files/get.ts index 8044bc1..3418d31 100644 --- a/src/commands/files/get.ts +++ b/src/commands/files/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { fileGetter, getterFn } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get a file.`; + public static readonly description = `Get a file.`; - public static examples = [ + public static readonly examples = [ `$ vertex files:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-file `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/files/list.ts b/src/commands/files/list.ts index e61f1fb..925007c 100644 --- a/src/commands/files/list.ts +++ b/src/commands/files/list.ts @@ -5,9 +5,9 @@ import { vertexClient } from '../../lib/client'; import { fileGetter, getterFn } from '../../lib/getter'; export default class List extends BaseListCommand { - public static description = `Get files.`; + public static readonly description = `Get files.`; - public static examples = [ + public static readonly examples = [ `$ vertex files:list Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-file-1 @@ -15,7 +15,7 @@ a8070713-e48e-466b-b4bb-b3132895d5ce my-file-2 `, ]; - public static flags = BaseListCommand.flags; + public static readonly flags = BaseListCommand.flags; public async run(): Promise { const { diff --git a/src/commands/part-revisions/render.ts b/src/commands/part-revisions/render.ts index 1cde03d..89798a8 100644 --- a/src/commands/part-revisions/render.ts +++ b/src/commands/part-revisions/render.ts @@ -11,17 +11,17 @@ import { vertexClient } from '../../lib/client'; import { createFile, validate, validateImage } from '../../lib/renderer'; export default class Render extends BaseRenderCommand { - public static description = `Render a part revision.`; + public static readonly description = `Render a part revision.`; - public static examples = [ + public static readonly examples = [ `$ vertex part-revisions:render 54964c61-05d8-4f37-9638-18f7c4960c80 54964c61-05d8-4f37-9638-18f7c4960c80.jpg `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseRenderCommand.flags; + public static readonly flags = BaseRenderCommand.flags; public async run(): Promise { const { diff --git a/src/commands/parts/delete.ts b/src/commands/parts/delete.ts index 6124fbb..d4d6c49 100644 --- a/src/commands/parts/delete.ts +++ b/src/commands/parts/delete.ts @@ -6,18 +6,18 @@ import { vertexClient } from '../../lib/client'; import { deleter, partDeleter, validate } from '../../lib/deleter'; export default class Delete extends BaseDeleteCommand { - public static description = `Delete parts.`; + public static readonly description = `Delete parts.`; - public static examples = [ + public static readonly examples = [ `$ vertex parts:delete 54964c61-05d8-4f37-9638-18f7c4960c80 Deleted part 54964c61-05d8-4f37-9638-18f7c4960c80. Deleting part(s)...... done `, ]; - public static args = [{ name: 'id' }]; + public static readonly args = [{ name: 'id' }]; - public static flags = BaseDeleteCommand.flags; + public static readonly flags = BaseDeleteCommand.flags; public async run(): Promise { const { diff --git a/src/commands/parts/get.ts b/src/commands/parts/get.ts index 83af33c..9b7efd2 100644 --- a/src/commands/parts/get.ts +++ b/src/commands/parts/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { getterFn, partGetter } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get a part.`; + public static readonly description = `Get a part.`; - public static examples = [ + public static readonly examples = [ `$ vertex parts:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-part `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/parts/list.ts b/src/commands/parts/list.ts index 754e532..8168db9 100644 --- a/src/commands/parts/list.ts +++ b/src/commands/parts/list.ts @@ -5,9 +5,9 @@ import { vertexClient } from '../../lib/client'; import { getterFn, partGetter } from '../../lib/getter'; export default class List extends BaseListCommand { - public static description = `Get parts.`; + public static readonly description = `Get parts.`; - public static examples = [ + public static readonly examples = [ `$ vertex parts:list Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-part-1 @@ -15,7 +15,7 @@ a8070713-e48e-466b-b4bb-b3132895d5ce my-part-2 `, ]; - public static flags = BaseListCommand.flags; + public static readonly flags = BaseListCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scene-items/get.ts b/src/commands/scene-items/get.ts index d123892..46bdde2 100644 --- a/src/commands/scene-items/get.ts +++ b/src/commands/scene-items/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneItemGetter } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get a scene item.`; + public static readonly description = `Get a scene item.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-items:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-item `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scene-items/list.ts b/src/commands/scene-items/list.ts index 79e3bed..53532f3 100644 --- a/src/commands/scene-items/list.ts +++ b/src/commands/scene-items/list.ts @@ -6,9 +6,9 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneItemGetter } from '../../lib/getter'; export default class List extends BaseListCommand { - public static description = `Get scene items.`; + public static readonly description = `Get scene items.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-items:list Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-item-1 @@ -16,7 +16,7 @@ a8070713-e48e-466b-b4bb-b3132895d5ce my-scene-item-2 `, ]; - public static flags = { + public static readonly flags = { ...BaseListCommand.flags, sceneId: flags.string({ description: `Scene to list scene items.`, diff --git a/src/commands/scene-trees/export.ts b/src/commands/scene-trees/export.ts index 235e3b2..0f00b1b 100644 --- a/src/commands/scene-trees/export.ts +++ b/src/commands/scene-trees/export.ts @@ -7,17 +7,17 @@ import { fetchSceneItemTree } from '../../lib/scene-items'; import { serializeTreeToZipFile } from '../../lib/tree-serializer'; export default class Export extends BaseCommand { - public static description = `Export a scene's scene item tree to a ZIP file.`; + public static readonly description = `Export a scene's scene item tree to a ZIP file.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-trees:export 54964c61-05d8-4f37-9638-18f7c4960c80 Tree saved to: 54964c61-05d8-4f37-9638-18f7c4960c80.zip `, ]; - public static args = [{ name: 'sceneId', required: true }]; + public static readonly args = [{ name: 'sceneId', required: true }]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, output: flags.string({ char: 'o', diff --git a/src/commands/scene-trees/view.ts b/src/commands/scene-trees/view.ts index ac35e37..50c0020 100644 --- a/src/commands/scene-trees/view.ts +++ b/src/commands/scene-trees/view.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { fetchSceneItemTree } from '../../lib/scene-items'; export default class View extends BaseCommand { - public static description = `View a scene's item tree.`; + public static readonly description = `View a scene's item tree.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-trees:view 54964c61-05d8-4f37-9638-18f7c4960c80 [TreeNode (root) has 3 child nodes, data=[...]] └── [TreeNode has 2 child nodes, data=[...]] `, ]; - public static args = [{ name: 'sceneId', required: true }]; + public static readonly args = [{ name: 'sceneId', required: true }]; - public static flags = BaseCommand.flags; + public static readonly flags = BaseCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scene-view-states/delete.ts b/src/commands/scene-view-states/delete.ts index 57b1bdb..02c40af 100644 --- a/src/commands/scene-view-states/delete.ts +++ b/src/commands/scene-view-states/delete.ts @@ -6,18 +6,18 @@ import { vertexClient } from '../../lib/client'; import { deleter, sceneViewStateDeleter, validate } from '../../lib/deleter'; export default class Delete extends BaseDeleteCommand { - public static description = `Delete scene-view-states.`; + public static readonly description = `Delete scene-view-states.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-view-states:delete 54964c61-05d8-4f37-9638-18f7c4960c80 Deleted scene view state 54964c61-05d8-4f37-9638-18f7c4960c80. Deleting scene view state(s)...... done `, ]; - public static args = [{ name: 'id' }]; + public static readonly args = [{ name: 'id' }]; - public static flags = BaseDeleteCommand.flags; + public static readonly flags = BaseDeleteCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scene-view-states/get.ts b/src/commands/scene-view-states/get.ts index 0ee7322..45e9e0e 100644 --- a/src/commands/scene-view-states/get.ts +++ b/src/commands/scene-view-states/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneViewStateGetter } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get a scene-view-state.`; + public static readonly description = `Get a scene-view-state.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-view-states:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-view-state `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scene-view-states/list.ts b/src/commands/scene-view-states/list.ts index df6890d..f60a939 100644 --- a/src/commands/scene-view-states/list.ts +++ b/src/commands/scene-view-states/list.ts @@ -6,9 +6,9 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneViewStateGetter } from '../../lib/getter'; export default class List extends BaseListCommand { - public static description = `Get scene-view-states.`; + public static readonly description = `Get scene-view-states.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-view-states:list Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-view-state-1 @@ -16,7 +16,7 @@ a8070713-e48e-466b-b4bb-b3132895d5ce my-scene-view-state-2 `, ]; - public static flags = { + public static readonly flags = { ...BaseListCommand.flags, sceneId: flags.string({ description: `Scene to list scene view states.`, diff --git a/src/commands/scene-views/create.ts b/src/commands/scene-views/create.ts index dbab134..8c36541 100644 --- a/src/commands/scene-views/create.ts +++ b/src/commands/scene-views/create.ts @@ -5,15 +5,15 @@ import BaseCommand from '../../lib/base'; import { vertexClient } from '../../lib/client'; export default class Create extends BaseCommand { - public static description = `Create a scene view for a scene.`; + public static readonly description = `Create a scene view for a scene.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-views:create --sceneId f79d4760-0b71-44e4-ad0b-22743fdd4ca3 bf0c4343-96eb-4aa9-8dee-e79c6458dedf `, ]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, sceneId: flags.string({ description: `Scene to base scene view on.`, diff --git a/src/commands/scene-views/get.ts b/src/commands/scene-views/get.ts index a27310f..1e53b68 100644 --- a/src/commands/scene-views/get.ts +++ b/src/commands/scene-views/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneViewGetter } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get a scene view.`; + public static readonly description = `Get a scene view.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-views:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-view `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scene-views/list.ts b/src/commands/scene-views/list.ts index 85d6142..fa6c977 100644 --- a/src/commands/scene-views/list.ts +++ b/src/commands/scene-views/list.ts @@ -6,9 +6,9 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneViewGetter } from '../../lib/getter'; export default class List extends BaseListCommand { - public static description = `Get scene views.`; + public static readonly description = `Get scene views.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-views:list Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-view-1 @@ -16,7 +16,7 @@ a8070713-e48e-466b-b4bb-b3132895d5ce my-scene-view-2 `, ]; - public static flags = { + public static readonly flags = { ...BaseListCommand.flags, sceneId: flags.string({ description: `Scene to list scene views.`, diff --git a/src/commands/scene-views/render.ts b/src/commands/scene-views/render.ts index 294368a..890dbb2 100644 --- a/src/commands/scene-views/render.ts +++ b/src/commands/scene-views/render.ts @@ -11,17 +11,17 @@ import { vertexClient } from '../../lib/client'; import { createFile, validate, validateImage } from '../../lib/renderer'; export default class Render extends BaseRenderCommand { - public static description = `Render a scene view.`; + public static readonly description = `Render a scene view.`; - public static examples = [ + public static readonly examples = [ `$ vertex scene-views:render 54964c61-05d8-4f37-9638-18f7c4960c80 54964c61-05d8-4f37-9638-18f7c4960c80.jpg `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseRenderCommand.flags; + public static readonly flags = BaseRenderCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scenes/delete.ts b/src/commands/scenes/delete.ts index 8cff3ba..996c112 100644 --- a/src/commands/scenes/delete.ts +++ b/src/commands/scenes/delete.ts @@ -6,18 +6,18 @@ import { vertexClient } from '../../lib/client'; import { deleter, sceneDeleter, validate } from '../../lib/deleter'; export default class Delete extends BaseDeleteCommand { - public static description = `Delete scenes.`; + public static readonly description = `Delete scenes.`; - public static examples = [ + public static readonly examples = [ `$ vertex scenes:delete 54964c61-05d8-4f37-9638-18f7c4960c80 Deleted scene 54964c61-05d8-4f37-9638-18f7c4960c80. Deleting scene(s)...... done `, ]; - public static args = [{ name: 'id' }]; + public static readonly args = [{ name: 'id' }]; - public static flags = BaseDeleteCommand.flags; + public static readonly flags = BaseDeleteCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scenes/get.ts b/src/commands/scenes/get.ts index ccf88de..5c49283 100644 --- a/src/commands/scenes/get.ts +++ b/src/commands/scenes/get.ts @@ -5,18 +5,18 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneGetter } from '../../lib/getter'; export default class Get extends BaseGetCommand { - public static description = `Get a scene.`; + public static readonly description = `Get a scene.`; - public static examples = [ + public static readonly examples = [ `$ vertex scenes:get 54964c61-05d8-4f37-9638-18f7c4960c80 Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = BaseGetCommand.flags; + public static readonly flags = BaseGetCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scenes/list.ts b/src/commands/scenes/list.ts index fc86336..5dea1ee 100644 --- a/src/commands/scenes/list.ts +++ b/src/commands/scenes/list.ts @@ -5,9 +5,9 @@ import { vertexClient } from '../../lib/client'; import { getterFn, sceneGetter } from '../../lib/getter'; export default class List extends BaseListCommand { - public static description = `Get scenes.`; + public static readonly description = `Get scenes.`; - public static examples = [ + public static readonly examples = [ `$ vertex scenes:list Id Name 54964c61-05d8-4f37-9638-18f7c4960c80 my-scene-1 @@ -15,7 +15,7 @@ a8070713-e48e-466b-b4bb-b3132895d5ce my-scene-2 `, ]; - public static flags = BaseListCommand.flags; + public static readonly flags = BaseListCommand.flags; public async run(): Promise { const { diff --git a/src/commands/scenes/render.ts b/src/commands/scenes/render.ts index dd749ae..ad0bb65 100644 --- a/src/commands/scenes/render.ts +++ b/src/commands/scenes/render.ts @@ -13,17 +13,17 @@ import { } from '../../lib/renderer'; export default class Render extends BaseRenderCommand { - public static description = `Render a scene.`; + public static readonly description = `Render a scene.`; - public static examples = [ + public static readonly examples = [ `$ vertex scenes:render 54964c61-05d8-4f37-9638-18f7c4960c80 54964c61-05d8-4f37-9638-18f7c4960c80.jpg `, ]; - public static args = [{ name: 'id', required: true }]; + public static readonly args = [{ name: 'id', required: true }]; - public static flags = { + public static readonly flags = { ...BaseRenderCommand.flags, viewer: flags.boolean({ description: 'Create Web SDK Viewer HTML instead of jpg image.', diff --git a/src/commands/stream-keys/create.ts b/src/commands/stream-keys/create.ts index 880d27e..f8a20cb 100644 --- a/src/commands/stream-keys/create.ts +++ b/src/commands/stream-keys/create.ts @@ -5,15 +5,15 @@ import BaseCommand from '../../lib/base'; import { vertexClient } from '../../lib/client'; export default class Create extends BaseCommand { - public static description = `Create a stream key for a scene.`; + public static readonly description = `Create a stream key for a scene.`; - public static examples = [ + public static readonly examples = [ `$ vertex stream-keys:create --sceneId f79d4760-0b71-44e4-ad0b-22743fdd4ca3 hBXAoQdnsHVhgDZkxeLEPQVxPJ600QwDMdgq `, ]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, expiry: flags.integer({ char: 'k', diff --git a/src/commands/webhook-subscriptions/create.ts b/src/commands/webhook-subscriptions/create.ts index 433edb2..2887c89 100644 --- a/src/commands/webhook-subscriptions/create.ts +++ b/src/commands/webhook-subscriptions/create.ts @@ -5,15 +5,15 @@ import BaseCommand from '../../lib/base'; import { vertexClient } from '../../lib/client'; export default class Create extends BaseCommand { - public static description = `Create a webhook subscription.`; + public static readonly description = `Create a webhook subscription.`; - public static examples = [ + public static readonly examples = [ `$ vertex webhook-subscriptions:create --topics queued-translation.completed,scene.updated --url https://example.com ta47eOIQtg13pSyf/PgpAB47r4JYJoAZfyzAcB5x8IHo+gQ `, ]; - public static flags = { + public static readonly flags = { ...BaseCommand.flags, topics: flags.string({ description: `Comma-separated list of topics.`, diff --git a/src/lib/base-delete.ts b/src/lib/base-delete.ts index 989fdd6..3f5bfba 100644 --- a/src/lib/base-delete.ts +++ b/src/lib/base-delete.ts @@ -4,7 +4,7 @@ import { Input, OutputFlags } from '@oclif/parser'; import BaseCommand from './base'; export default abstract class BaseDeleteCommand extends BaseCommand { - public static flags = { + public static readonly flags = { ...BaseCommand.flags, all: flags.boolean({ description: 'Delete all resources.', diff --git a/src/lib/base-get.ts b/src/lib/base-get.ts index 0e64236..e04b32d 100644 --- a/src/lib/base-get.ts +++ b/src/lib/base-get.ts @@ -4,7 +4,7 @@ import { Input, OutputFlags } from '@oclif/parser'; import BaseCommand from './base'; export default abstract class BaseGetCommand extends BaseCommand { - public static flags = { + public static readonly flags = { ...BaseCommand.flags, extended: flags.boolean({ description: 'Display extended output.', diff --git a/src/lib/base-list.ts b/src/lib/base-list.ts index a63073a..3a4ced8 100644 --- a/src/lib/base-list.ts +++ b/src/lib/base-list.ts @@ -4,7 +4,7 @@ import { Input, OutputFlags } from '@oclif/parser'; import BaseGetCommand from './base-get'; export default abstract class BaseListCommand extends BaseGetCommand { - public static flags = { + public static readonly flags = { ...BaseGetCommand.flags, cursor: flags.string({ description: 'Cursor for next page of items.', diff --git a/src/lib/base-render.ts b/src/lib/base-render.ts index 228ab53..2b161ae 100644 --- a/src/lib/base-render.ts +++ b/src/lib/base-render.ts @@ -4,7 +4,7 @@ import { Input, OutputFlags } from '@oclif/parser'; import BaseCommand from './base'; export default abstract class BaseRenderCommand extends BaseCommand { - public static flags = { + public static readonly flags = { ...BaseCommand.flags, height: flags.integer({ char: 'h', diff --git a/src/lib/base.ts b/src/lib/base.ts index 4e622af..2d7ed03 100644 --- a/src/lib/base.ts +++ b/src/lib/base.ts @@ -20,7 +20,7 @@ BasePathAliases.set('platdev', 'https://platform.platdev.vertexvis.io'); BasePathAliases.set('platstaging', 'https://platform.platstaging.vertexvis.io'); export default abstract class BaseCommand extends Command { - public static flags = { + public static readonly flags = { help: flags.help({ char: 'h' }), basePath: flags.string({ char: 'b', From cc319f302e9dbb18d7ba9a5a7f0e02655b860711 Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Thu, 19 Feb 2026 14:39:19 -0600 Subject: [PATCH 5/6] Addressed sonar findings --- src/lib/tree-serializer.ts | 48 ++++++++++---------------- test/commands/scene-trees/view.test.ts | 7 ++-- test/lib/tree-node.test.ts | 6 ++-- 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/lib/tree-serializer.ts b/src/lib/tree-serializer.ts index 744164b..c48b4ad 100644 --- a/src/lib/tree-serializer.ts +++ b/src/lib/tree-serializer.ts @@ -18,12 +18,12 @@ * const tree3 = deserializeTreeFromBuffer({ buffer: gzBuf }); */ import archiver from 'archiver'; -import fs from 'fs'; -import path from 'path'; -import { pipeline, Readable, Transform } from 'stream'; -import { finished } from 'stream/promises'; -import { promisify } from 'util'; -import zlib from 'zlib'; +import fs from 'node:fs'; +import path from 'node:path'; +import { pipeline, Readable, Transform } from 'node:stream'; +import { finished } from 'node:stream/promises'; +import { promisify } from 'node:util'; +import zlib from 'node:zlib'; import { TreeNode } from './tree-node'; @@ -32,6 +32,16 @@ interface SerializedNode { children: SerializedNode[]; } +function buildTreeFromSerialized(obj: SerializedNode): TreeNode { + const node = new TreeNode(obj.data); + for (const childObj of obj.children) { + const child = buildTreeFromSerialized(childObj); + child.parent = node; + node.children.push(child); + } + return node; +} + export interface SerializeFileOptions { /** Root TreeNode to serialize */ root: TreeNode; @@ -115,18 +125,7 @@ export function deserializeTreeFromFile({ // fallback to full parse—if your JSON is enormous you can // also hook in a streaming parser like `stream-json` const parsed = JSON.parse(json) as SerializedNode; - - function build(obj: SerializedNode): TreeNode { - const node = new TreeNode(obj.data); - for (const childObj of obj.children) { - const child = build(childObj); - child.parent = node; - node.children.push(child); - } - return node; - } - - return build(parsed); + return buildTreeFromSerialized(parsed); } export interface BufferSerializeOptions { @@ -231,18 +230,7 @@ export function deserializeTreeFromBuffer({ const dataBuf = isGz ? zlib.gunzipSync(buffer as Uint8Array) : buffer; const parsed = JSON.parse(dataBuf.toString('utf8')) as SerializedNode; - // Rebuild TreeNode - const build = (obj: SerializedNode): TreeNode => { - const node = new TreeNode(obj.data); - for (const childObj of obj.children) { - const child = build(childObj); - child.parent = node; - node.children.push(child); - } - return node; - }; - - return build(parsed); + return buildTreeFromSerialized(parsed); } export interface SerializeZipFileOptions { diff --git a/test/commands/scene-trees/view.test.ts b/test/commands/scene-trees/view.test.ts index fc09c46..66226de 100644 --- a/test/commands/scene-trees/view.test.ts +++ b/test/commands/scene-trees/view.test.ts @@ -33,8 +33,11 @@ describe('scene-trees:view', () => { const root = new TreeNode({ id: 'root-id', } as SceneItemData); - // eslint-disable-next-line no-new - new TreeNode({ id: 'child-id' } as SceneItemData, root); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const child = new TreeNode( + { id: 'child-id' } as SceneItemData, + root + ); sinon.stub(si, 'fetchSceneItemTree').resolves(root); await new View([sceneId], {} as IConfig).run(); diff --git a/test/lib/tree-node.test.ts b/test/lib/tree-node.test.ts index f1ffcae..338fdee 100644 --- a/test/lib/tree-node.test.ts +++ b/test/lib/tree-node.test.ts @@ -5,13 +5,13 @@ import { TreeNode } from '../../src/lib/tree-node'; describe('TreeNode', () => { let root: TreeNode; let child1: TreeNode; + let child2: TreeNode; let grandchild: TreeNode; beforeEach(() => { root = new TreeNode('root'); child1 = new TreeNode('child1', root); - // eslint-disable-next-line no-new - new TreeNode('child2', root); + child2 = new TreeNode('child2', root); grandchild = new TreeNode('grandchild', child1); }); @@ -25,7 +25,9 @@ describe('TreeNode', () => { it('links to parent and adds itself to parent children', () => { expect(child1.parent).to.equal(root); + expect(child2.parent).to.equal(root); expect(root.children).to.include(child1); + expect(root.children).to.include(child2); }); }); From c883e6b2c4729e1f75bb6ec7583a2a082694d1ee Mon Sep 17 00:00:00 2001 From: Brent Arndorfer Date: Thu, 19 Feb 2026 15:12:37 -0600 Subject: [PATCH 6/6] Resolved build issue --- package.json | 2 +- test/commands/scene-trees/view.test.ts | 5 ----- yarn.lock | 8 ++++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 3d6f10f..08be2a1 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@types/chai": "^4.3", "@types/fs-extra": "^9.0", "@types/mocha": "^9", - "@types/node": "^16", + "@types/node": "~16.11.26", "@vertexvis/eslint-config-vertexvis-typescript": "0.4", "chai": "^4.3", "eslint": "^7", diff --git a/test/commands/scene-trees/view.test.ts b/test/commands/scene-trees/view.test.ts index 66226de..b09a2d3 100644 --- a/test/commands/scene-trees/view.test.ts +++ b/test/commands/scene-trees/view.test.ts @@ -33,11 +33,6 @@ describe('scene-trees:view', () => { const root = new TreeNode({ id: 'root-id', } as SceneItemData); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const child = new TreeNode( - { id: 'child-id' } as SceneItemData, - root - ); sinon.stub(si, 'fetchSceneItemTree').resolves(root); await new View([sceneId], {} as IConfig).run(); diff --git a/yarn.lock b/yarn.lock index 4bf44fc..e8225f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -626,10 +626,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da" integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw== -"@types/node@^16": - version "16.18.126" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.126.tgz#27875faa2926c0f475b39a8bb1e546c0176f8d4b" - integrity sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw== +"@types/node@~16.11.26": + version "16.11.68" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.68.tgz#30ee923f4d940793e0380f5ce61c0bd4b7196b6c" + integrity sha512-JkRpuVz3xCNCWaeQ5EHLR/6woMbHZz/jZ7Kmc63AkU+1HxnoUugzSWMck7dsR4DvNYX8jp9wTi9K7WvnxOIQZQ== "@types/readdir-glob@*": version "1.1.5"