diff --git a/.changeset/five-rice-raise.md b/.changeset/five-rice-raise.md new file mode 100644 index 0000000..dc32dff --- /dev/null +++ b/.changeset/five-rice-raise.md @@ -0,0 +1,7 @@ +--- +'@contentauth/c2pa-types': minor +'@contentauth/c2pa-wasm': minor +'@contentauth/c2pa-web': minor +--- + +Added reader.manifestStore() and reader.activeManifest() APIs diff --git a/Cargo.lock b/Cargo.lock index 7e6894f..ddb4949 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -359,6 +359,7 @@ dependencies = [ "riff", "ring", "rsa", + "schemars 0.8.22", "serde", "serde-transcode", "serde-wasm-bindgen", @@ -391,6 +392,15 @@ dependencies = [ "zip", ] +[[package]] +name = "c2pa-types" +version = "0.1.0" +dependencies = [ + "c2pa", + "schemars 0.8.22", + "serde_json", +] + [[package]] name = "c2pa-wasm" version = "0.1.0" @@ -401,6 +411,8 @@ dependencies = [ "console_log", "js-sys", "log", + "serde", + "serde-wasm-bindgen", "thiserror 2.0.12", "wasm-bindgen", "wasm-bindgen-futures", @@ -2623,6 +2635,18 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + [[package]] name = "schemars" version = "0.9.0" @@ -2647,6 +2671,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.104", +] + [[package]] name = "sec1" version = "0.7.3" @@ -2726,11 +2762,22 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "serde_json" -version = "1.0.141" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "indexmap 2.10.0", "itoa", diff --git a/Cargo.toml b/Cargo.toml index 2c525da..7118e77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = '2' members = [ 'packages/c2pa-wasm', + 'packages/c2pa-types', ] [profile.release] diff --git a/packages/c2pa-types/.gitignore b/packages/c2pa-types/.gitignore new file mode 100644 index 0000000..85807ad --- /dev/null +++ b/packages/c2pa-types/.gitignore @@ -0,0 +1,2 @@ +schemas +types \ No newline at end of file diff --git a/packages/c2pa-types/Cargo.toml b/packages/c2pa-types/Cargo.toml new file mode 100644 index 0000000..ed8d56f --- /dev/null +++ b/packages/c2pa-types/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "c2pa-types" +version = "0.1.0" +edition = "2024" + +[dependencies] +c2pa = { version = "0.62.0", features = ["pdf", "rust_native_crypto", "json_schema"], default-features = false } +schemars = "0.8.21" +serde_json = "1.0.143" diff --git a/packages/c2pa-types/index.d.ts b/packages/c2pa-types/index.d.ts new file mode 100644 index 0000000..3bcda61 --- /dev/null +++ b/packages/c2pa-types/index.d.ts @@ -0,0 +1,16 @@ +/** + * Copyright 2025 Adobe + * All Rights Reserved. + * + * NOTICE: Adobe permits you to use, modify, and distribute this file in + * accordance with the terms of the Adobe license agreement accompanying + * it. + */ + +import type { Reader } from './types/ManifestStore.js'; + +// Renames the auto-generated "Reader" type to the more appropriate "ManifestStore" +// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-empty-object-type +export interface ManifestStore extends Reader {} + +export type { Manifest } from './types/ManifestStore.js'; diff --git a/packages/c2pa-types/package.json b/packages/c2pa-types/package.json new file mode 100644 index 0000000..c127847 --- /dev/null +++ b/packages/c2pa-types/package.json @@ -0,0 +1,17 @@ +{ + "name": "@contentauth/c2pa-types", + "description": "Typescript types generated from c2pa-rs", + "type": "module", + "version": "0.1.1", + "types": "index.d.ts", + "scripts": { + "test": "echo \"No tests to run\" && exit 0", + "build": "pnpm clean && json2ts -i schemas/ -o types/", + "clean": "rimraf types" + }, + "files": ["index.d.ts", "types/**/*"], + "dependencies": { + "json-schema-to-typescript": "^15.0.4", + "rimraf": "^6.0.1" + } +} diff --git a/packages/c2pa-types/project.json b/packages/c2pa-types/project.json new file mode 100644 index 0000000..525e6b4 --- /dev/null +++ b/packages/c2pa-types/project.json @@ -0,0 +1,26 @@ +{ + "name": "c2pa-types", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "tags": ["lib"], + "projectType": "library", + "sourceRoot": "packages/c2pa-types/src", + "targets": { + "build": { + "cache": true, + "inputs": [ + "{projectRoot}/**/*", + "!{projectRoot}/schemas/**/*", + "!{projectRoot}/types/**/*" + ], + "executor": "nx:run-commands", + "options": { + "commands": [ + "cargo run", + "pnpm build" + ], + "parallel": false, + "cwd": "{projectRoot}" + } + } + } +} \ No newline at end of file diff --git a/packages/c2pa-types/src/main.rs b/packages/c2pa-types/src/main.rs new file mode 100644 index 0000000..0bce466 --- /dev/null +++ b/packages/c2pa-types/src/main.rs @@ -0,0 +1,31 @@ +// Copyright 2025 Adobe +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying +// it. + +use std::{fs, path::Path}; + +use c2pa::Reader; +use schemars::{schema::RootSchema, schema_for}; + +fn main() { + let output_dir = Path::new("./schemas"); + + if fs::exists(output_dir).unwrap() { + fs::remove_dir_all(output_dir).expect("Could not clear existing schema directory"); + } + + fs::create_dir_all(output_dir).expect("Could not create schema directory"); + + write_schema(&schema_for!(Reader), &"ManifestStore", output_dir); +} + +fn write_schema(schema: &RootSchema, name: &str, output_dir: &Path) { + println!("Exporting JSON schema for {name}"); + let output_path = output_dir.join(format!("{name}.json")); + let output = serde_json::to_string_pretty(schema).expect("Failed to serialize schema"); + fs::write(&output_path, output).expect("Unable to write schema"); + println!("Wrote schema to {}", output_path.display()); +} diff --git a/packages/c2pa-wasm/Cargo.toml b/packages/c2pa-wasm/Cargo.toml index 4b165ef..345bfbf 100644 --- a/packages/c2pa-wasm/Cargo.toml +++ b/packages/c2pa-wasm/Cargo.toml @@ -25,6 +25,8 @@ wasm-bindgen-futures = "0.4.50" c2pa = { version = "0.62.0", features = ["pdf", "rust_native_crypto", "fetch_remote_manifests"], default-features = false } async-trait = "0.1.88" thiserror = "2.0.12" +serde-wasm-bindgen = "0.6.5" +serde = "1.0.219" [dependencies.web-sys] version = "0.3.77" diff --git a/packages/c2pa-wasm/src/error.rs b/packages/c2pa-wasm/src/error.rs index 318ef24..5640c36 100644 --- a/packages/c2pa-wasm/src/error.rs +++ b/packages/c2pa-wasm/src/error.rs @@ -14,6 +14,9 @@ pub enum WasmError { #[error(transparent)] C2pa(#[from] c2pa::Error), + #[error(transparent)] + Serde(#[from] serde_wasm_bindgen::Error), + #[error(transparent)] Other(Box), } diff --git a/packages/c2pa-wasm/src/wasm_reader.rs b/packages/c2pa-wasm/src/wasm_reader.rs index fd70d50..f0d1526 100644 --- a/packages/c2pa-wasm/src/wasm_reader.rs +++ b/packages/c2pa-wasm/src/wasm_reader.rs @@ -9,6 +9,8 @@ use std::io::{Cursor, Read, Seek}; use c2pa::{identity::validator::CawgValidator, Reader}; use js_sys::{ArrayBuffer, Error as JsError, Uint8Array}; +use serde::Serialize; +use serde_wasm_bindgen::Serializer; use wasm_bindgen::prelude::*; use web_sys::Blob; @@ -18,6 +20,7 @@ use crate::{error::WasmError, stream::BlobStream}; #[wasm_bindgen] pub struct WasmReader { reader: Reader, + serializer: Serializer, } #[wasm_bindgen] @@ -33,17 +36,11 @@ impl WasmReader { format: &str, stream: impl Read + Seek + Send, ) -> Result { - let mut reader = Reader::from_stream_async(format, stream) + let reader = Reader::from_stream_async(format, stream) .await .map_err(WasmError::from)?; - // This will be removed once CawgValidation is rolled into the reader - reader - .post_validate_async(&CawgValidator {}) - .await - .map_err(WasmError::other)?; - - Ok(WasmReader { reader }) + Ok(WasmReader::from_reader(reader).await?) } /// Attempts to create a new `WasmReader` from an asset format, a `Blob` of the bytes of the initial segment, and a fragment `Blob`. @@ -64,23 +61,23 @@ impl WasmReader { init: impl Read + Seek + Send, fragment: impl Read + Seek + Send, ) -> Result { - let mut reader = Reader::from_fragment_async(format, init, fragment) + let reader = Reader::from_fragment_async(format, init, fragment) .await .map_err(WasmError::other)?; + Ok(WasmReader::from_reader(reader).await?) + } + + async fn from_reader(mut reader: Reader) -> Result { + let serializer = Serializer::new().serialize_maps_as_objects(true); + // This will be removed once CawgValidation is rolled into the reader reader .post_validate_async(&CawgValidator {}) .await .map_err(WasmError::other)?; - Ok(WasmReader { reader }) - } - - /// Returns a JSON representation of the asset's manifest store. - #[wasm_bindgen] - pub fn json(&self) -> String { - self.reader.json() + Ok(WasmReader { reader, serializer }) } /// Returns the label of the asset's active manifest. @@ -89,6 +86,37 @@ impl WasmReader { self.reader.active_label().map(|val| val.to_owned()) } + /// Returns the asset's manifest store. + /// NOTE: at the moment, CAWG data is not decoded via this function. Use WasmReader::json() if CAWG is a requirement. + #[wasm_bindgen(js_name = manifestStore)] + pub fn manifest_store(&self) -> Result { + let manifest_store = self + .reader + .serialize(&self.serializer) + .map_err(WasmError::from)?; + + Ok(manifest_store) + } + + /// Returns the asset's active manifest. + /// NOTE: at the moment, CAWG data is not decoded via this function. Use WasmReader::json() if CAWG is a requirement. + #[wasm_bindgen(js_name = activeManifest)] + pub fn active_manifest(&self) -> Result { + let active_manifest = self + .reader + .active_manifest() + .serialize(&self.serializer) + .map_err(WasmError::from)?; + + Ok(active_manifest) + } + + /// Returns a JSON representation of the asset's manifest store. + #[wasm_bindgen] + pub fn json(&self) -> String { + self.reader.json() + } + /// Accepts a URI reference to a binary object in the resource store and returns a `js_sys::ArrayBuffer` containing the resource's bytes. #[wasm_bindgen(js_name = resourceToBuffer)] pub fn resource_to_buffer(&self, uri: &str) -> Result { diff --git a/packages/c2pa-web/package.json b/packages/c2pa-web/package.json index c0c922e..2621107 100644 --- a/packages/c2pa-web/package.json +++ b/packages/c2pa-web/package.json @@ -30,7 +30,8 @@ } }, "dependencies": { - "@contentauth/c2pa-wasm": "workspace:*" + "@contentauth/c2pa-wasm": "workspace:*", + "@contentauth/c2pa-types": "workspace:*" }, "devDependencies": { "@playwright/test": "^1.55.0", diff --git a/packages/c2pa-web/src/index.ts b/packages/c2pa-web/src/index.ts index 9ac266b..8da798c 100644 --- a/packages/c2pa-web/src/index.ts +++ b/packages/c2pa-web/src/index.ts @@ -8,8 +8,13 @@ */ export * from './lib/c2pa.js'; + export { isSupportedReaderFormat, READER_SUPPORTED_FORMATS, } from './lib/supportedFormats.js'; + export { type Settings } from './lib/settings.js'; + +// Re-export types from c2pa-types for convenience. +export type * from '@contentauth/c2pa-types'; diff --git a/packages/c2pa-web/src/lib/c2pa.spec.ts b/packages/c2pa-web/src/lib/c2pa.spec.ts index cca9f7e..51fdb5d 100644 --- a/packages/c2pa-web/src/lib/c2pa.spec.ts +++ b/packages/c2pa-web/src/lib/c2pa.spec.ts @@ -35,7 +35,7 @@ describe('c2pa', () => { const reader = await c2pa.reader.fromBlob(blob.type, blob); - const manifestStore = await reader.manifestStore(); + const manifestStore = await reader.json(); expect(manifestStore).toEqual(C_with_CAWG_data_ManifestStore); @@ -49,11 +49,11 @@ describe('c2pa', () => { const reader = await c2pa.reader.fromBlob(blob.type, blob); - const manifestStore = await reader.manifestStore(); + const manifestStore = await reader.json(); const activeManifest = - manifestStore.manifests[manifestStore.active_manifest]; - const thumbnailId = activeManifest.thumbnail.identifier; + manifestStore.manifests[manifestStore.active_manifest!]; + const thumbnailId = activeManifest.thumbnail!.identifier; const thumbnailBuffer = await reader.resourceToBuffer(thumbnailId); const thumbnail = new Uint8Array(thumbnailBuffer!); @@ -100,7 +100,7 @@ describe('c2pa', () => { const reader = await c2pa.reader.fromBlob(blob.type, blob); - const manifestStore = await reader.manifestStore(); + const manifestStore = await reader.json(); expect(manifestStore).toEqual(C_with_CAWG_data_trusted_ManifestStore); @@ -123,7 +123,7 @@ describe('c2pa', () => { const reader = await c2pa.reader.fromBlob(blob.type, blob); - const manifestStore = await reader.manifestStore(); + const manifestStore = await reader.json(); expect(manifestStore).toEqual(C_with_CAWG_data_untrusted_ManifestStore); @@ -142,7 +142,7 @@ describe('c2pa', () => { fragmentBlob ); - const manifestStore = await reader.manifestStore(); + const manifestStore = await reader.json(); expect(manifestStore).toEqual(dashinit_ManifestStore); @@ -159,7 +159,7 @@ describe('c2pa', () => { await reader.free(); - await expect(reader.manifestStore()).rejects.toThrowError(); + await expect(reader.json()).rejects.toThrowError(); }); }); }); diff --git a/packages/c2pa-web/src/lib/reader.ts b/packages/c2pa-web/src/lib/reader.ts index b8d22b1..4faa5cb 100644 --- a/packages/c2pa-web/src/lib/reader.ts +++ b/packages/c2pa-web/src/lib/reader.ts @@ -7,6 +7,7 @@ * it. */ +import { Manifest, ManifestStore } from '@contentauth/c2pa-types'; import { AssetTooLargeError, UnsupportedFormatError } from './error.js'; import { isSupportedReaderFormat } from './supportedFormats.js'; import type { WorkerManager } from './worker/workerManager.js'; @@ -32,15 +33,29 @@ export interface ReaderFactory { } export interface Reader { + /** + * @returns The label of the active manifest. + */ + activeLabel: () => Promise; + /** * @returns The asset's full manifest store containing all its manifests, validation statuses, and the URI of the active manifest. + * + * NOTE: At the moment, the manifest store returned by this method will not include decoded CAWG data. Use Reader.json() if CAWG is a requirement. */ - manifestStore: () => Promise; + manifestStore: () => Promise; /** - * @returns The label of the active manifest. + * @returns The asset's active manifest. + * + * NOTE: At the moment, the manifest returned by this method will not include decoded CAWG data. Use Reader.json() if CAWG is a requirement. */ - activeLabel: () => Promise; + activeManifest: () => Promise; + + /** + * @returns The asset's full manifest store, including decoded CAWG data. + */ + json: () => Promise; /** * Resolves a URI reference to a binary object (e.g. a thumbnail) in the resource store. @@ -121,14 +136,6 @@ function createReader( onFree: () => void ): Reader { return { - // TODO: manifest type - async manifestStore(): Promise { - const json = await worker.execute({ method: 'reader_json', args: [id] }); - - const manifestStore = JSON.parse(json); - - return manifestStore; - }, async activeLabel(): Promise { const label = await worker.execute({ method: 'reader_activeLabel', @@ -136,6 +143,28 @@ function createReader( }); return label; }, + async manifestStore(): Promise { + const manifestStore = await worker.execute({ + method: 'reader_manifestStore', + args: [id], + }); + return manifestStore; + }, + async activeManifest(): Promise { + const activeManifest = await worker.execute({ + method: 'reader_activeManifest', + args: [id], + }); + + return activeManifest; + }, + async json(): Promise { + const json = await worker.execute({ method: 'reader_json', args: [id] }); + + const manifestStore = JSON.parse(json); + + return manifestStore; + }, async resourceToBuffer(uri: string): Promise { return worker.execute({ method: 'reader_resourceToBuffer', diff --git a/packages/c2pa-web/src/lib/worker.ts b/packages/c2pa-web/src/lib/worker.ts index cbb35ef..82ec093 100644 --- a/packages/c2pa-web/src/lib/worker.ts +++ b/packages/c2pa-web/src/lib/worker.ts @@ -49,14 +49,22 @@ const workerFunctions = { }, // Reader object methods - reader_json(readerId: number): WorkerResponse { - const reader = readerMap.get(readerId); - return { data: reader.json() }; - }, reader_activeLabel(readerId: number): WorkerResponse { const reader = readerMap.get(readerId); return { data: reader.activeLabel() ?? null }; }, + reader_manifestStore(readerId: number): WorkerResponse { + const reader = readerMap.get(readerId); + return { data: reader.manifestStore() }; + }, + reader_activeManifest(readerId: number): WorkerResponse { + const reader = readerMap.get(readerId); + return { data: reader.activeManifest() }; + }, + reader_json(readerId: number): WorkerResponse { + const reader = readerMap.get(readerId); + return { data: reader.json() }; + }, reader_resourceToBuffer( readerId: number, uri: string diff --git a/packages/c2pa-web/vite.config.ts b/packages/c2pa-web/vite.config.ts index b3a06af..78d9e6d 100644 --- a/packages/c2pa-web/vite.config.ts +++ b/packages/c2pa-web/vite.config.ts @@ -41,7 +41,7 @@ export default defineConfig(() => ({ }, rollupOptions: { // External packages that should not be bundled into your library. - external: [], + external: ['@contentauth/c2pa-types'], }, }, server: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4730e9d..388d7f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -102,10 +102,22 @@ importers: specifier: ^3.0.0 version: 3.2.4(@types/node@18.16.9)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.4.2)(jsdom@22.1.0)(terser@5.43.1)(yaml@2.8.0) + packages/c2pa-types: + dependencies: + json-schema-to-typescript: + specifier: ^15.0.4 + version: 15.0.4 + rimraf: + specifier: ^6.0.1 + version: 6.0.1 + packages/c2pa-wasm: {} packages/c2pa-web: dependencies: + '@contentauth/c2pa-types': + specifier: workspace:* + version: link:../c2pa-types '@contentauth/c2pa-wasm': specifier: workspace:* version: link:../c2pa-wasm @@ -159,6 +171,10 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@apidevtools/json-schema-ref-parser@11.9.3': + resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==} + engines: {node: '>= 16'} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1293,6 +1309,9 @@ packages: '@jridgewell/trace-mapping@0.3.29': resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==} + '@jsdevtools/ono@7.1.3': + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + '@ltd/j-toml@1.38.0': resolution: {integrity: sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==} @@ -2267,6 +2286,9 @@ packages: '@types/jsonfile@6.1.4': resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + '@types/lodash@4.17.20': + resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} @@ -3858,6 +3880,11 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-to-typescript@15.0.4: + resolution: {integrity: sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==} + engines: {node: '>=16.0.0'} + hasBin: true + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -4316,6 +4343,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -5088,6 +5120,12 @@ snapshots: '@jridgewell/gen-mapping': 0.3.12 '@jridgewell/trace-mapping': 0.3.29 + '@apidevtools/json-schema-ref-parser@11.9.3': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.0 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -6477,6 +6515,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.4 + '@jsdevtools/ono@7.1.3': {} + '@ltd/j-toml@1.38.0': {} '@manypkg/find-root@1.1.0': @@ -7510,6 +7550,8 @@ snapshots: dependencies: '@types/node': 18.16.9 + '@types/lodash@4.17.20': {} + '@types/node@12.20.55': {} '@types/node@18.16.9': {} @@ -9412,6 +9454,18 @@ snapshots: json-parse-even-better-errors@2.3.1: {} + json-schema-to-typescript@15.0.4: + dependencies: + '@apidevtools/json-schema-ref-parser': 11.9.3 + '@types/json-schema': 7.0.15 + '@types/lodash': 4.17.20 + is-glob: 4.0.3 + js-yaml: 4.1.0 + lodash: 4.17.21 + minimist: 1.2.8 + prettier: 3.6.2 + tinyglobby: 0.2.14 + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -9857,6 +9911,8 @@ snapshots: prettier@2.8.8: {} + prettier@3.6.2: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1