diff --git a/examples/full_example/README.md b/examples/full_example/README.md new file mode 100644 index 0000000..62269f4 --- /dev/null +++ b/examples/full_example/README.md @@ -0,0 +1,17 @@ +# full_example + +This example showcases how to use the runtime with `Typescript` and `Node Modules`. + +## Install the runtime + +- `dart pub global activate globe_cli` + +- `globe runtime install` + +## Run the code + +- `pnpm install` + +- `pnpm run generate` + +- `dart run lib/full_example.dart` diff --git a/examples/full_example/lib/full_example.dart b/examples/full_example/lib/full_example.dart new file mode 100644 index 0000000..1ce3bc9 --- /dev/null +++ b/examples/full_example/lib/full_example.dart @@ -0,0 +1,81 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:full_example/full_example_source.dart'; + +void main() async { + final fullExample = await FullExample.create(language: 'en', verbose: true); + + final prettyBytes = await fullExample.makePrettyBytes(569943344333884); + print('Pretty Bytes: $prettyBytes'); + + final prettyMs = await fullExample.makePrettyMs(8003333); + print('Pretty MS: $prettyMs'); + + final sum = await fullExample.calculateSum(10, 20); + print('Sum: $sum'); + + final average = await fullExample.calculateAverage([10, 20, 30, 40, 50]); + print('Average: $average'); + + final isValid = await fullExample.isValid('a'); + print('Is Valid: $isValid'); + + final bytes = await fullExample.generateBytes(10); + print('Bytes: $bytes'); + + final metadata = await fullExample.getMetadata('1'); + print('Metadata: $metadata'); + + final items = await fullExample.getItems(10); + print('Items: $items'); + + final uniqueValues = + await fullExample.getUniqueValues([1, 2, 2, 3, 3, 3, 4, 5, 4]); + print('Unique Values: $uniqueValues'); + + final messages = await fullExample.streamMessages(10); + final completer = Completer(); + messages.listen((message) { + print('Message: $message'); + }, onDone: completer.complete); + + await completer.future; + + final integers = await fullExample.streamIntegers(10); + final integerCompleter = Completer(); + integers.listen((integer) { + print('Integer: $integer'); + }, onDone: integerCompleter.complete); + + await integerCompleter.future; + + final randomNumbers = await fullExample.streamRandomNumbers(10); + final randomNumbersCompleter = Completer(); + randomNumbers.listen((randomNumber) { + print('Random Number: $randomNumber'); + }, onDone: randomNumbersCompleter.complete); + + await randomNumbersCompleter.future; + + final updates = await fullExample.streamUpdates(10); + final updatesCompleter = Completer(); + updates.listen((update) { + print('Update: $update'); + }, onDone: updatesCompleter.complete); + + await updatesCompleter.future; + + final batches = await fullExample.streamBatches(10, 10); + final batchesCompleter = Completer(); + batches.listen((batch) { + print('Batch: $batch'); + }, onDone: batchesCompleter.complete); + + await batchesCompleter.future; + + print('Done'); + fullExample.dispose(); + + exit(0); +} diff --git a/examples/full_example/lib/full_example.ts b/examples/full_example/lib/full_example.ts new file mode 100644 index 0000000..1992ae7 --- /dev/null +++ b/examples/full_example/lib/full_example.ts @@ -0,0 +1,231 @@ +import pretty_bytes from "pretty-bytes"; +import pretty_ms from "pretty-ms"; +import { + defineSdk, + returnString, + returnInt, + returnDouble, + returnBoolean, + returnUint8Array, + returnMap, + returnList, + returnSet, + streamString, + streamInt, + streamNumber, + streamMap, + streamList, +} from "@globe/runtime_types"; + +type Language = "en" | "fr" | "es"; + +type ModuleState = { + language: Language; + verbose: boolean; +}; + +// ====================================================== +// Single Value Functions - All Supported Types +// ====================================================== + +// String return (Dart: String, JS: string) +const make_pretty_bytes = returnString( + (state: ModuleState, value: number, callbackId: number) => { + const str = pretty_bytes(value, { locale: state.language }); + Dart.send_value(callbackId, new TextEncoder().encode(str)); + } +); + +// String return (Dart: String, JS: string) +const make_pretty_ms = returnString( + (state: ModuleState, value: number, callbackId: number) => { + const str = pretty_ms(value, { verbose: state.verbose }); + Dart.send_value(callbackId, new TextEncoder().encode(str)); + } +); + +// Int return (Dart: int, JS: number) +const calculate_sum = returnInt( + (state: ModuleState, a: number, b: number, callbackId: number) => { + const result = Math.floor(a + b); + Dart.send_value(callbackId, new TextEncoder().encode(result.toString())); + } +); + +// Double return (Dart: double, JS: number) +const calculate_average = returnDouble( + (state: ModuleState, values: number[], callbackId: number) => { + const sum = values.reduce((acc, val) => acc + val, 0); + const avg = sum / values.length; + Dart.send_value(callbackId, new TextEncoder().encode(avg.toString())); + } +); + +// Boolean return (Dart: bool, JS: boolean) +const is_valid = returnBoolean( + (state: ModuleState, value: string, callbackId: number) => { + const isValid = value.length > 0; + Dart.send_value(callbackId, JsonPayload.encode(isValid)!); + } +); + +// Uint8Array return (Dart: List, JS: Uint8Array) +const generate_bytes = returnUint8Array( + (state: ModuleState, length: number, callbackId: number) => { + const bytes = new Uint8Array(length); + for (let i = 0; i < length; i++) { + bytes[i] = Math.floor(Math.random() * 256); + } + Dart.send_value(callbackId, bytes); + } +); + +// Map return (Dart: Map, JS: object) +const get_metadata = returnMap( + (state: ModuleState, id: string, callbackId: number) => { + const metadata = { + id, + language: state.language, + timestamp: Date.now(), + nested: { + key: "value", + }, + }; + const encoded = JsonPayload.encode(metadata); + if (encoded) { + Dart.send_value(callbackId, encoded); + } + } +); + +// List return (Dart: List, JS: object) +const get_items = returnList( + (state: ModuleState, count: number, callbackId: number) => { + const items = Array.from({ length: count }, (_, i) => ({ + id: i, + name: `Item ${i}`, + })); + const encoded = JsonPayload.encode(items); + if (encoded) { + Dart.send_value(callbackId, encoded); + } + } +); + +// Set return (Dart: Set, JS: object) +const get_unique_values = returnSet( + (state: ModuleState, values: number[], callbackId: number) => { + const uniqueValues = [...new Set(values)]; + const encoded = JsonPayload.encode(uniqueValues); + if (encoded) { + Dart.send_value(callbackId, encoded); + } + } +); + +// ====================================================== +// Streaming Functions - All Supported Types +// ====================================================== + +// Stream (Dart: Stream, JS: string) +const stream_messages = streamString( + (state: ModuleState, count: number, callbackId: number) => { + for (let i = 0; i < count; i++) { + const message = `Message ${i + 1} in ${state.language}`; + Dart.stream_value(callbackId, new TextEncoder().encode(message)); + } + Dart.stream_value_end(callbackId); + } +); + +// Stream (Dart: Stream, JS: number) +const stream_integers = streamInt( + (state: ModuleState, max: number, callbackId: number) => { + for (let i = 0; i < max; i++) { + Dart.stream_value(callbackId, new TextEncoder().encode(i.toString())); + } + Dart.stream_value_end(callbackId); + } +); + +// Stream (Dart: Stream, JS: number) +const stream_random_numbers = streamNumber( + (state: ModuleState, count: number, callbackId: number) => { + for (let i = 0; i < count; i++) { + const num = Math.random() * 1000; + Dart.stream_value(callbackId, new TextEncoder().encode(num.toString())); + } + Dart.stream_value_end(callbackId); + } +); + +// Stream> (Dart: Stream>, JS: object) +const stream_updates = streamMap( + async (state: ModuleState, count: number, callbackId: number) => { + for (let i = 0; i < count; i++) { + const update = { + index: i, + timestamp: Date.now(), + language: state.language, + }; + // Pause for 100ms + await new Promise((resolve) => setTimeout(resolve, 100)); + const encoded = JsonPayload.encode(update); + if (encoded) { + Dart.stream_value(callbackId, encoded); + } + } + Dart.stream_value_end(callbackId); + } +); + +// Stream> (Dart: Stream>, JS: object) +const stream_batches = streamList( + ( + state: ModuleState, + batchCount: number, + batchSize: number, + callbackId: number + ) => { + for (let i = 0; i < batchCount; i++) { + const batch = Array.from( + { length: batchSize }, + (_, j) => i * batchSize + j + ); + const encoded = JsonPayload.encode(batch); + if (encoded) { + Dart.stream_value(callbackId, encoded); + } + } + Dart.stream_value_end(callbackId); + } +); + +// ====================================================== +// SDK Definition +// ====================================================== + +export default defineSdk({ + init(language: Language = "en", verbose: boolean = false): ModuleState { + return { language, verbose }; + }, + functions: { + // Single value functions + make_pretty_bytes, + make_pretty_ms, + calculate_sum, + calculate_average, + is_valid, + generate_bytes, + get_metadata, + get_items, + get_unique_values, + + // Streaming functions + stream_messages, + stream_integers, + stream_random_numbers, + stream_updates, + stream_batches, + }, +}); diff --git a/examples/full_example/lib/full_example_source.dart b/examples/full_example/lib/full_example_source.dart new file mode 100644 index 0000000..d137671 --- /dev/null +++ b/examples/full_example/lib/full_example_source.dart @@ -0,0 +1,409 @@ +// GENERATED FILE — DO NOT MODIFY BY HAND +// This file was generated from @globe/dart_source_generator +// ignore_for_file: unused_import + +import 'dart:async'; +import 'dart:convert'; +import 'package:globe_runtime/globe_runtime.dart'; + +/// Package version +const packageVersion = '1.0.0'; + +/// Package source code +const packageSource = r''' +const e=[`B`,`kB`,`MB`,`GB`,`TB`,`PB`,`EB`,`ZB`,`YB`],t=[`B`,`KiB`,`MiB`,`GiB`,`TiB`,`PiB`,`EiB`,`ZiB`,`YiB`],n=[`b`,`kbit`,`Mbit`,`Gbit`,`Tbit`,`Pbit`,`Ebit`,`Zbit`,`Ybit`],r=[`b`,`kibit`,`Mibit`,`Gibit`,`Tibit`,`Pibit`,`Eibit`,`Zibit`,`Yibit`],i=(e,t,n)=>{let r=e;return typeof t==`string`||Array.isArray(t)?r=e.toLocaleString(t,n):(t===!0||n!==void 0)&&(r=e.toLocaleString(void 0,n)),r},a=e=>{if(typeof e==`number`)return Math.log10(e);let t=e.toString(10);return t.length+Math.log10(`0.${t.slice(0,15)}`)},o=e=>typeof e==`number`?Math.log(e):a(e)*Math.log(10),s=(e,t)=>{if(typeof e==`number`)return e/t;let n=e/BigInt(t),r=e%BigInt(t);return Number(n)+Number(r)/t},c=(e,t)=>{if(t===void 0)return e;if(typeof t!=`number`||!Number.isSafeInteger(t)||t<0)throw TypeError(`Expected fixedWidth to be a non-negative integer, got ${typeof t}: ${t}`);return t===0?e:e.length{let{minimumFractionDigits:t,maximumFractionDigits:n}=e;if(!(t===void 0&&n===void 0))return{...t!==void 0&&{minimumFractionDigits:t},...n!==void 0&&{maximumFractionDigits:n},roundingMode:`trunc`}};function u(u,d){if(typeof u!=`bigint`&&!Number.isFinite(u))throw TypeError(`Expected a finite number, got ${typeof u}: ${u}`);d={bits:!1,binary:!1,space:!0,nonBreakingSpace:!1,...d};let f=d.bits?d.binary?r:n:d.binary?t:e,p=d.space?d.nonBreakingSpace?`\xA0`:` `:``,m=typeof u==`number`?u===0:u===0n;if(d.signed&&m)return c(` 0${p}${f[0]}`,d.fixedWidth);let h=u<0,g=h?`-`:d.signed?`+`:``;h&&(u=-u);let _=l(d),v;if(u<1)v=g+i(u,d.locale,_)+p+f[0];else{let e=Math.min(Math.floor(d.binary?o(u)/Math.log(1024):a(u)/3),f.length-1);if(u=s(u,(d.binary?1024:1e3)**e),!_){let e=Math.max(3,Math.floor(u).toString().length);u=u.toPrecision(e)}let t=i(Number(u),d.locale,_),n=f[e];v=g+t+p+n}return c(v,d.fixedWidth)}const d=e=>Number.isFinite(e)?e:0;function f(e){return{days:Math.trunc(e/864e5),hours:Math.trunc(e/36e5%24),minutes:Math.trunc(e/6e4%60),seconds:Math.trunc(e/1e3%60),milliseconds:Math.trunc(e%1e3),microseconds:Math.trunc(d(e*1e3)%1e3),nanoseconds:Math.trunc(d(e*1e6)%1e3)}}function p(e){return{days:e/86400000n,hours:e/3600000n%24n,minutes:e/60000n%60n,seconds:e/1000n%60n,milliseconds:e%1000n,microseconds:0n,nanoseconds:0n}}function m(e){switch(typeof e){case`number`:if(Number.isFinite(e))return f(e);break;case`bigint`:return p(e)}throw TypeError(`Expected a finite number or bigint`)}const h=e=>e===0||e===0n,g=(e,t)=>t===1||t===1n?e:`${e}s`,_=24n*60n*60n*1000n;function v(e,t){let n=typeof e==`bigint`;if(!n&&!Number.isFinite(e))throw TypeError(`Expected a finite number or bigint`);t={...t};let r=e<0?`-`:``;e=e<0?-e:e,t.colonNotation&&(t.compact=!1,t.formatSubMilliseconds=!1,t.separateMilliseconds=!1,t.verbose=!1),t.compact&&(t.unitCount=1,t.secondsDecimalDigits=0,t.millisecondsDecimalDigits=0);let i=[],a=(e,t)=>{let n=Math.floor(e*10**t+1e-7);return(Math.round(n)/10**t).toFixed(t)},o=(e,n,r,a)=>{if(!((i.length===0||!t.colonNotation)&&h(e)&&!(t.colonNotation&&r===`m`))){if(a??=String(e),t.colonNotation){let e=a.includes(`.`)?a.split(`.`)[0].length:a.length,t=i.length>0?2:1;a=`0`.repeat(Math.max(0,t-e))+a}else a+=t.verbose?` `+g(n,e):r;i.push(a)}},s=m(e),c=BigInt(s.days);if(t.hideYearAndDays?o(BigInt(c)*24n+BigInt(s.hours),`hour`,`h`):(t.hideYear?o(c,`day`,`d`):(o(c/365n,`year`,`y`),o(c%365n,`day`,`d`)),o(Number(s.hours),`hour`,`h`)),o(Number(s.minutes),`minute`,`m`),!t.hideSeconds)if(t.separateMilliseconds||t.formatSubMilliseconds||!t.colonNotation&&e<1e3&&!t.subSecondsAsDecimals){let e=Number(s.seconds),n=Number(s.milliseconds),r=Number(s.microseconds),i=Number(s.nanoseconds);if(o(e,`second`,`s`),t.formatSubMilliseconds)o(n,`millisecond`,`ms`),o(r,`microsecond`,`µs`),o(i,`nanosecond`,`ns`);else{let e=n+r/1e3+i/1e6,a=typeof t.millisecondsDecimalDigits==`number`?t.millisecondsDecimalDigits:0,s=a?e.toFixed(a):e>=1?Math.round(e):Math.ceil(e);o(Number.parseFloat(s),`millisecond`,`ms`,s)}}else{let r=a((n?Number(e%_):e)/1e3%60,typeof t.secondsDecimalDigits==`number`?t.secondsDecimalDigits:1),i=t.keepDecimalsOnWholeSeconds?r:r.replace(/\.0+$/,``);o(Number.parseFloat(i),`second`,`s`,i)}if(i.length===0)return r+`0`+(t.verbose?` milliseconds`:`ms`);let l=t.colonNotation?`:`:` `;return typeof t.unitCount==`number`&&(i=i.slice(0,Math.max(t.unitCount,1))),r+i.join(l)}globalThis.Dart??={},globalThis.JsonPayload??={};const y=()=>function(e){return e},b=y,x=y,S=b(),C=b(),w=b();b();const T=b(),E=b(),D=b(),O=b(),k=b(),A=x(),j=x();x();const M=x();x(),x();const N=x(),P=x();x();var F=y()({init(e=`en`,t=!1){return{language:e,verbose:t}},functions:{make_pretty_bytes:S((e,t,n)=>{let r=u(t,{locale:e.language});Dart.send_value(n,new TextEncoder().encode(r))}),make_pretty_ms:S((e,t,n)=>{let r=v(t,{verbose:e.verbose});Dart.send_value(n,new TextEncoder().encode(r))}),calculate_sum:C((e,t,n,r)=>{let i=Math.floor(t+n);Dart.send_value(r,new TextEncoder().encode(i.toString()))}),calculate_average:w((e,t,n)=>{let r=t.reduce((e,t)=>e+t,0)/t.length;Dart.send_value(n,new TextEncoder().encode(r.toString()))}),is_valid:T((e,t,n)=>{let r=t.length>0;Dart.send_value(n,JsonPayload.encode(r))}),generate_bytes:E((e,t,n)=>{let r=new Uint8Array(t);for(let e=0;e{let r={id:t,language:e.language,timestamp:Date.now(),nested:{key:`value`}},i=JsonPayload.encode(r);i&&Dart.send_value(n,i)}),get_items:O((e,t,n)=>{let r=Array.from({length:t},(e,t)=>({id:t,name:`Item ${t}`})),i=JsonPayload.encode(r);i&&Dart.send_value(n,i)}),get_unique_values:k((e,t,n)=>{let r=[...new Set(t)],i=JsonPayload.encode(r);i&&Dart.send_value(n,i)}),stream_messages:A((e,t,n)=>{for(let r=0;r{for(let e=0;e{for(let e=0;e{for(let r=0;rsetTimeout(e,100));let i=JsonPayload.encode(t);i&&Dart.stream_value(n,i)}Dart.stream_value_end(n)}),stream_batches:P((e,t,n,r)=>{for(let e=0;ee*n+r),i=JsonPayload.encode(t);i&&Dart.stream_value(r,i)}Dart.stream_value_end(r)})}});export{F as default}; +'''; + +/// {@template FullExample} +/// FullExample class +/// {@endtemplate} +class FullExample { + /// {@macro FullExample} + FullExample._(this._module); + + /// Module instance + final Module _module; + + /// Create instance of FullExample class + static Future create({String? language, bool? verbose}) async { + const module = InlinedModule( + name: 'FullExample', + sourceCode: packageSource, + ); + + await module.register(args: [language?.toFFIType, verbose?.toFFIType]); + return FullExample._(module); + } + + /// Disposes of the runtime instance + void dispose() { + GlobeRuntime.instance.dispose(); + } + + /// makePrettyBytes function + /// + /// **Returns:** `Future` + Future makePrettyBytes(num value) async { + final completer = Completer(); + + _module.callFunction( + 'make_pretty_bytes', + args: [value.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data; + completer.complete(utf8.decode(value)); + } + return true; + }, + ); + + return completer.future; + } + + /// makePrettyMs function + /// + /// **Returns:** `Future` + Future makePrettyMs(num value) async { + final completer = Completer(); + + _module.callFunction( + 'make_pretty_ms', + args: [value.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data; + completer.complete(utf8.decode(value)); + } + return true; + }, + ); + + return completer.future; + } + + /// calculateSum function + /// + /// **Returns:** `Future` + Future calculateSum(num a, num b) async { + final completer = Completer(); + + _module.callFunction( + 'calculate_sum', + args: [a.toFFIType, b.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as num); + } + return true; + }, + ); + + return completer.future; + } + + /// calculateAverage function + /// + /// **Returns:** `Future` + Future calculateAverage(List values) async { + final completer = Completer(); + + _module.callFunction( + 'calculate_average', + args: [values.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as num); + } + return true; + }, + ); + + return completer.future; + } + + /// isValid function + /// + /// **Returns:** `Future` + Future isValid(String value) async { + final completer = Completer(); + + _module.callFunction( + 'is_valid', + args: [value.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as bool); + } + return true; + }, + ); + + return completer.future; + } + + /// generateBytes function + /// + /// **Returns:** `Future>` + Future> generateBytes(num length) async { + final completer = Completer>(); + + _module.callFunction( + 'generate_bytes', + args: [length.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data; + completer.complete(value); + } + return true; + }, + ); + + return completer.future; + } + + /// getMetadata function + /// + /// **Returns:** `Future>` + Future> getMetadata(String id) async { + final completer = Completer>(); + + _module.callFunction( + 'get_metadata', + args: [id.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as Map); + } + return true; + }, + ); + + return completer.future; + } + + /// getItems function + /// + /// **Returns:** `Future>` + Future> getItems(num count) async { + final completer = Completer>(); + + _module.callFunction( + 'get_items', + args: [count.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as List); + } + return true; + }, + ); + + return completer.future; + } + + /// getUniqueValues function + /// + /// **Returns:** `Future>` + Future> getUniqueValues(List values) async { + final completer = Completer>(); + + _module.callFunction( + 'get_unique_values', + args: [values.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(Set.from(value)); + } + return true; + }, + ); + + return completer.future; + } + + /// streamMessages function + /// + /// **Returns:** `Stream` + Stream streamMessages(num count) { + final controller = StreamController(); + + _module.callFunction( + 'stream_messages', + args: [count.toFFIType], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data; + controller.add(utf8.decode(value)); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + + /// streamIntegers function + /// + /// **Returns:** `Stream` + Stream streamIntegers(num max) { + final controller = StreamController(); + + _module.callFunction( + 'stream_integers', + args: [max.toFFIType], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data.unpack(); + controller.add(value as num); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + + /// streamRandomNumbers function + /// + /// **Returns:** `Stream` + Stream streamRandomNumbers(num count) { + final controller = StreamController(); + + _module.callFunction( + 'stream_random_numbers', + args: [count.toFFIType], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data.unpack(); + controller.add(value as num); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + + /// streamUpdates function + /// + /// **Returns:** `Stream>` + Stream> streamUpdates(num count) { + final controller = StreamController>(); + + _module.callFunction( + 'stream_updates', + args: [count.toFFIType], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data.unpack(); + controller.add(value as Map); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + + /// streamBatches function + /// + /// **Returns:** `Stream>` + Stream> streamBatches(num batchCount, num batchSize) { + final controller = StreamController>(); + + _module.callFunction( + 'stream_batches', + args: [batchCount.toFFIType, batchSize.toFFIType], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data.unpack(); + controller.add(value as List); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } +} diff --git a/examples/full_example/package-lock.json b/examples/full_example/package-lock.json new file mode 100644 index 0000000..bf8ea08 --- /dev/null +++ b/examples/full_example/package-lock.json @@ -0,0 +1,133 @@ +{ + "name": "full_example", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "full_example", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "pretty-bytes": "^7.1.0", + "pretty-ms": "^9.3.0" + }, + "devDependencies": { + "@globe/dart_source_generator": "../../packages/globe_runtime_ts/dart_source_generator", + "@globe/runtime_types": "../../packages/globe_runtime_ts/runtime_types", + "@types/node": "^25.0.2", + "typescript": "^5.9.3" + } + }, + "../../packages/globe_runtime_ts": { + "name": "@globe/runtime_types", + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "../../packages/globe_runtime_ts/dart_source_generator": { + "name": "@globe/dart_source_generator", + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^13.0.0", + "tsdown": "0.17.4", + "tslog": "^4.10.2", + "typescript": "^5.9.3" + }, + "bin": { + "globe-dart-source-generator": "dist/bin/generate.js" + }, + "devDependencies": { + "@types/node": "^25.0.2", + "@vitest/coverage-v8": "^4.0.15", + "vitest": "^4.0.15" + } + }, + "../../packages/globe_runtime_ts/runtime_types": { + "name": "@globe/runtime_types", + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@globe/dart_source_generator": { + "resolved": "../../packages/globe_runtime_ts/dart_source_generator", + "link": true + }, + "node_modules/@globe/runtime_types": { + "resolved": "../../packages/globe_runtime_ts/runtime_types", + "link": true + }, + "node_modules/@types/node": { + "version": "25.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.2.tgz", + "integrity": "sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-bytes": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-7.1.0.tgz", + "integrity": "sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/examples/full_example/package.json b/examples/full_example/package.json new file mode 100644 index 0000000..249ea0f --- /dev/null +++ b/examples/full_example/package.json @@ -0,0 +1,22 @@ +{ + "name": "full_example", + "version": "1.0.0", + "description": "", + "type": "module", + "keywords": [], + "author": "", + "license": "ISC", + "scripts": { + "generate": "npx @globe/dart_source_generator --input ./lib --output ./lib" + }, + "dependencies": { + "pretty-bytes": "^7.1.0", + "pretty-ms": "^9.3.0" + }, + "devDependencies": { + "@globe/runtime_types": "workspace:*", + "@globe/dart_source_generator": "workspace:*", + "@types/node": "catalog:", + "typescript": "catalog:" + } +} diff --git a/examples/full_example/pubspec.lock b/examples/full_example/pubspec.lock new file mode 100644 index 0000000..797a29f --- /dev/null +++ b/examples/full_example/pubspec.lock @@ -0,0 +1,444 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "5b7468c326d2f8a4f630056404ca0d291ade42918f4a3c6233618e724f39da8e" + url: "https://pub.dev" + source: hosted + version: "92.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "70e4b1ef8003c64793a9e268a551a82869a8a96f39deb73dea28084b0e8bf75e" + url: "https://pub.dev" + source: hosted + version: "9.0.0" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + globe_runtime: + dependency: "direct main" + description: + path: "../../packages/globe_runtime" + relative: true + source: path + version: "1.0.8" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + lints: + dependency: "direct dev" + description: + name: lints + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + url: "https://pub.dev" + source: hosted + version: "6.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + msgpack_dart: + dependency: transitive + description: + name: msgpack_dart + sha256: c2d235ed01f364719b5296aecf43ac330f0d7bc865fa134d0d7910a40454dffb + url: "https://pub.dev" + source: hosted + version: "1.0.1" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + rps: + dependency: "direct dev" + description: + name: rps + sha256: "7a2b9a1751506a9fcaba0af11e0d84115295a7a4b8cbf84ea178283588f7c010" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" + source: hosted + version: "1.10.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test: + dependency: "direct dev" + description: + name: test + sha256: "77cc98ea27006c84e71a7356cf3daf9ddbde2d91d84f77dbfe64cf0e4d9611ae" + url: "https://pub.dev" + source: hosted + version: "1.28.0" + test_api: + dependency: transitive + description: + name: test_api + sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8" + url: "https://pub.dev" + source: hosted + version: "0.7.8" + test_core: + dependency: transitive + description: + name: test_core + sha256: f1072617a6657e5fc09662e721307f7fb009b4ed89b19f47175d11d5254a62d4 + url: "https://pub.dev" + source: hosted + version: "0.6.14" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "6f82e9ee8e7339f5d8b699317f6f3afc17c80a68ebef1bc0d6f52a678c14b1e6" + url: "https://pub.dev" + source: hosted + version: "15.0.1" + watcher: + dependency: transitive + description: + name: watcher + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.9.0 <4.0.0" diff --git a/examples/full_example/pubspec.yaml b/examples/full_example/pubspec.yaml new file mode 100644 index 0000000..b965398 --- /dev/null +++ b/examples/full_example/pubspec.yaml @@ -0,0 +1,19 @@ +name: full_example +version: 1.0.0 +description: A Dart package that uses @globe/dart_source_generator to generate Dart code from Node.js modules. +publish_to: none + +environment: + sdk: ^3.4.0 + +dependencies: + globe_runtime: "^1.0.8" + + +dev_dependencies: + lints: ^6.0.0 + test: ^1.24.0 + rps: ^0.7.0 + +scripts: + build: npm run generate \ No newline at end of file diff --git a/examples/full_example/tsconfig.json b/examples/full_example/tsconfig.json new file mode 100644 index 0000000..cce220b --- /dev/null +++ b/examples/full_example/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "lib": ["ES2016"], + "types": ["@globe/runtime_types", "node"], + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +} diff --git a/examples/js_to_dart_docs/README.md b/examples/js_to_dart_docs/README.md new file mode 100644 index 0000000..7a035ab --- /dev/null +++ b/examples/js_to_dart_docs/README.md @@ -0,0 +1,18 @@ +# js_to_dart_docs + +This example showcases how to use the runtime with `Typescript` and `Node Modules`. +It also showcases how to generate a Dart file from a Typescript file while preserving the documentation. + +## Install the runtime + +- `dart pub global activate globe_cli` + +- `globe runtime install` + +## Run the code + +- `pnpm install` + +- `pnpm run generate` + +- `dart run lib/js_to_dart_docs.dart` diff --git a/examples/js_to_dart_docs/lib/js_to_dart_docs.ts b/examples/js_to_dart_docs/lib/js_to_dart_docs.ts new file mode 100644 index 0000000..d7dfcb5 --- /dev/null +++ b/examples/js_to_dart_docs/lib/js_to_dart_docs.ts @@ -0,0 +1,117 @@ +import { + defineSdk, + returnMap, + returnNumber, + streamString, +} from "@globe/runtime_types"; + +type ModuleState = { + apiUrl: string; + timeout?: number; +}; + +export default defineSdk({ + /** + * Initialize the SDK with authentication credentials + * + * This sets up the SDK with your API key and configures the timeout + * for all network requests. + * + * @param apiUrl - Your API url to fetch data from + * @param timeout - Request timeout in milliseconds + */ + init(apiUrl: string, timeout?: number): ModuleState { + const defaultTimeoutMs = 5000; + return { apiUrl, timeout: timeout ?? defaultTimeoutMs }; + }, + functions: { + /** + * Stream all users from the API + * + * @returns A list of users encoded as a JSON string + */ + streamAllUsers: streamString( + async (state: ModuleState, callbackId: number) => { + try { + const url = `${state.apiUrl}/users`; + + const response = await fetch(url); + + if (!response.body) { + Dart.send_error(callbackId, "Response body is null"); + return; + } + + for await (const chunk of response.body.values()) { + Dart.stream_value(callbackId, chunk); + } + + Dart.stream_value_end(callbackId); + } catch (error) { + Dart.send_error( + callbackId, + `Streaming users failed: ${(error as Error).message}` + ); + } + } + ), + + /** + * Fetches user data from the API + * + * This function retrieves user information based on the provided user ID. + * It handles authentication automatically using the configured API key. + * + * @param userId - The unique identifier for the user + * @returns A JSON string containing the user's profile information + */ + getUserData: returnMap( + async (state: ModuleState, userId: number, callbackId: number) => { + try { + const url = `${state.apiUrl}/users/${userId}`; + + const response = await fetch(url); + + const data = await response.json(); + + const encoded = JsonPayload.encode(data); + if (!encoded) { + Dart.send_error(callbackId, "Failed to encode response"); + return; + } + + Dart.send_value(callbackId, encoded); + } catch (error) { + Dart.send_error( + callbackId, + `Fetching user data with userId (${userId}) failed: ${ + (error as Error).message + }` + ); + } + } + ), + + /** + * Calculates the sum of two numbers + * @param a - First number + * @param b - Second number + * @returns The sum of a and b + */ + calculateSum: returnNumber( + (state: ModuleState, a: number, b: number, callbackId: number) => { + try { + const sum = a + b; + Dart.send_value(callbackId, JsonPayload.encode(sum)); + } catch (error) { + Dart.send_error( + callbackId, + `Calculating sum of ${a} and ${b} failed: ${ + (error as Error).message + }` + ); + } + } + ), + }, +}); diff --git a/examples/js_to_dart_docs/lib/js_to_dart_docs_source.dart b/examples/js_to_dart_docs/lib/js_to_dart_docs_source.dart new file mode 100644 index 0000000..a68d9c4 --- /dev/null +++ b/examples/js_to_dart_docs/lib/js_to_dart_docs_source.dart @@ -0,0 +1,137 @@ +// GENERATED FILE — DO NOT MODIFY BY HAND +// This file was generated from @globe/dart_source_generator +// ignore_for_file: unused_import + +import 'dart:async'; +import 'dart:convert'; +import 'package:globe_runtime/globe_runtime.dart'; + +/// Package version +const packageVersion = '1.0.0'; + +/// Package source code +const packageSource = r''' +globalThis.Dart??={},globalThis.JsonPayload??={};const e=()=>function(e){return e},t=e,n=e;t(),t(),t();const r=t();t(),t();const i=t();t(),t();const a=n();n(),n(),n(),n(),n(),n(),n(),n();var o=e()({init(e,t){return{apiUrl:e,timeout:t??5e3}},functions:{streamAllUsers:a(async(e,t)=>{try{let n=`${e.apiUrl}/users`,r=await fetch(n);if(!r.body){Dart.send_error(t,`Response body is null`);return}for await(let e of r.body.values())Dart.stream_value(t,e);Dart.stream_value_end(t)}catch(e){Dart.send_error(t,`Streaming users failed: ${e.message}`)}}),getUserData:i(async(e,t,n)=>{try{let r=`${e.apiUrl}/users/${t}`,i=await(await fetch(r)).json(),a=JsonPayload.encode(i);if(!a){Dart.send_error(n,`Failed to encode response`);return}Dart.send_value(n,a)}catch(e){Dart.send_error(n,`Fetching user data with userId (${t}) failed: ${e.message}`)}}),calculateSum:r((e,t,n,r)=>{try{let e=t+n;Dart.send_value(r,JsonPayload.encode(e))}catch(e){Dart.send_error(r,`Calculating sum of ${t} and ${n} failed: ${e.message}`)}})}});export{o as default}; +'''; + +/// {@template JsToDartDocs} +/// JsToDartDocs class +/// {@endtemplate} +class JsToDartDocs { + /// {@macro JsToDartDocs} + JsToDartDocs._(this._module); + + /// Module instance + final Module _module; + + /// Initialize the SDK with authentication credentials + /// + /// This sets up the SDK with your API key and configures the timeout for all + /// network requests. + /// + /// **Parameters:** + /// * [apiUrl]: Your API url to fetch data from + /// * [timeout]: Request timeout in milliseconds + static Future create({String? apiUrl, num? timeout}) async { + const module = InlinedModule( + name: 'JsToDartDocs', + sourceCode: packageSource, + ); + + await module.register(args: [apiUrl?.toFFIType, timeout?.toFFIType]); + return JsToDartDocs._(module); + } + + /// Disposes of the runtime instance + void dispose() { + GlobeRuntime.instance.dispose(); + } + + /// Stream all users from the API + /// + /// **Returns:** `A list of users encoded as a JSON string` + Stream streamAllUsers() { + final controller = StreamController(); + + _module.callFunction( + 'streamAllUsers', + args: [], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data; + controller.add(utf8.decode(value)); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + + /// Fetches user data from the API + /// + /// This function retrieves user information based on the provided user ID. It + /// handles authentication automatically using the configured API key. + /// + /// **Parameters:** + /// * [userId]: The unique identifier for the user + /// + /// **Returns:** `A JSON string containing the user's profile information` + Future> getUserData(num userId) async { + final completer = Completer>(); + + _module.callFunction( + 'getUserData', + args: [userId.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as Map); + } + return true; + }, + ); + + return completer.future; + } + + /// Calculates the sum of two numbers + /// + /// **Parameters:** + /// * [a]: First number + /// * [b]: Second number + /// + /// **Returns:** `The sum of a and b` + Future calculateSum(num a, num b) async { + final completer = Completer(); + + _module.callFunction( + 'calculateSum', + args: [a.toFFIType, b.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as num); + } + return true; + }, + ); + + return completer.future; + } +} diff --git a/examples/js_to_dart_docs/lib/js_to_dart_docs_usage.dart b/examples/js_to_dart_docs/lib/js_to_dart_docs_usage.dart new file mode 100644 index 0000000..e3f2586 --- /dev/null +++ b/examples/js_to_dart_docs/lib/js_to_dart_docs_usage.dart @@ -0,0 +1,41 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'js_to_dart_docs_source.dart'; + +void main() async { + print('Initializing runtime for JsToDartDocs...'); + // Initialize the runtime + final sdk = + await JsToDartDocs.create(apiUrl: 'https://jsonplaceholder.typicode.com'); + print('Runtime initialized for JsToDartDocs'); + + // Stream all users + final completer = Completer(); + String users = ''; + sdk.streamAllUsers().listen((chunk) { + print('Users streamed: $chunk'); + users += chunk; + }, onDone: completer.complete); + await completer.future; + final usersJson = jsonDecode(users) as List; + print('Users: ${usersJson.length}'); + + // Get user data + final userId = usersJson.isNotEmpty ? usersJson.first['id'] : ''; + print('First user ID: $userId'); + + final userData = await sdk.getUserData(userId); + print('User data: $userData'); + + // Calculate sum + final sum = await sdk.calculateSum(10, 20); + print('Sum: $sum'); + + // Dispose + print('Disposing runtime for JsToDartDocs...'); + sdk.dispose(); + + exit(0); +} diff --git a/examples/js_to_dart_docs/package.json b/examples/js_to_dart_docs/package.json new file mode 100644 index 0000000..08c2977 --- /dev/null +++ b/examples/js_to_dart_docs/package.json @@ -0,0 +1,23 @@ +{ + "name": "js_to_dart_docs", + "version": "1.0.0", + "description": "", + "type": "module", + "keywords": [], + "author": "", + "license": "ISC", + "scripts": { + "generate": "npx @globe/dart_source_generator --input ./lib --output ./lib", + "watch": "npm run generate -- --watch" + }, + "dependencies": { + "pretty-bytes": "^7.1.0", + "pretty-ms": "^9.3.0" + }, + "devDependencies": { + "@globe/runtime_types": "workspace:*", + "@globe/dart_source_generator": "workspace:*", + "@types/node": "catalog:", + "typescript": "catalog:" + } +} diff --git a/examples/js_to_dart_docs/pubspec.lock b/examples/js_to_dart_docs/pubspec.lock new file mode 100644 index 0000000..797a29f --- /dev/null +++ b/examples/js_to_dart_docs/pubspec.lock @@ -0,0 +1,444 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "5b7468c326d2f8a4f630056404ca0d291ade42918f4a3c6233618e724f39da8e" + url: "https://pub.dev" + source: hosted + version: "92.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "70e4b1ef8003c64793a9e268a551a82869a8a96f39deb73dea28084b0e8bf75e" + url: "https://pub.dev" + source: hosted + version: "9.0.0" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + globe_runtime: + dependency: "direct main" + description: + path: "../../packages/globe_runtime" + relative: true + source: path + version: "1.0.8" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + lints: + dependency: "direct dev" + description: + name: lints + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 + url: "https://pub.dev" + source: hosted + version: "6.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + msgpack_dart: + dependency: transitive + description: + name: msgpack_dart + sha256: c2d235ed01f364719b5296aecf43ac330f0d7bc865fa134d0d7910a40454dffb + url: "https://pub.dev" + source: hosted + version: "1.0.1" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + rps: + dependency: "direct dev" + description: + name: rps + sha256: "7a2b9a1751506a9fcaba0af11e0d84115295a7a4b8cbf84ea178283588f7c010" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" + source: hosted + version: "1.10.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test: + dependency: "direct dev" + description: + name: test + sha256: "77cc98ea27006c84e71a7356cf3daf9ddbde2d91d84f77dbfe64cf0e4d9611ae" + url: "https://pub.dev" + source: hosted + version: "1.28.0" + test_api: + dependency: transitive + description: + name: test_api + sha256: "19a78f63e83d3a61f00826d09bc2f60e191bf3504183c001262be6ac75589fb8" + url: "https://pub.dev" + source: hosted + version: "0.7.8" + test_core: + dependency: transitive + description: + name: test_core + sha256: f1072617a6657e5fc09662e721307f7fb009b4ed89b19f47175d11d5254a62d4 + url: "https://pub.dev" + source: hosted + version: "0.6.14" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "6f82e9ee8e7339f5d8b699317f6f3afc17c80a68ebef1bc0d6f52a678c14b1e6" + url: "https://pub.dev" + source: hosted + version: "15.0.1" + watcher: + dependency: transitive + description: + name: watcher + sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.9.0 <4.0.0" diff --git a/examples/js_to_dart_docs/pubspec.yaml b/examples/js_to_dart_docs/pubspec.yaml new file mode 100644 index 0000000..53eb859 --- /dev/null +++ b/examples/js_to_dart_docs/pubspec.yaml @@ -0,0 +1,20 @@ +name: js_to_dart_docs +version: 1.0.0 +description: A Dart package that uses @globe/dart_source_generator to generate a Dart file from a Typescript file while preserving the documentation. +publish_to: none + +environment: + sdk: ^3.4.0 + +dependencies: + globe_runtime: "^1.0.8" + + +dev_dependencies: + lints: ^6.0.0 + test: ^1.24.0 + rps: ^0.7.0 + +scripts: + build: npm run generate + watch: npm run generate -- --watch \ No newline at end of file diff --git a/examples/js_to_dart_docs/tsconfig.json b/examples/js_to_dart_docs/tsconfig.json new file mode 100644 index 0000000..cce220b --- /dev/null +++ b/examples/js_to_dart_docs/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es2016", + "module": "commonjs", + "lib": ["ES2016"], + "types": ["@globe/runtime_types", "node"], + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +} diff --git a/examples/pretty_node/lib/pretty_node.ts b/examples/pretty_node/lib/pretty_node.ts index 288053e..5c9a9fb 100644 --- a/examples/pretty_node/lib/pretty_node.ts +++ b/examples/pretty_node/lib/pretty_node.ts @@ -23,8 +23,5 @@ export default { init: (..._: any[]): ModuleState => { return {}; }, - functions: { - make_pretty_bytes, - make_pretty_ms, - }, + functions: { make_pretty_bytes, make_pretty_ms }, }; diff --git a/examples/pretty_node/lib/pretty_node_source.dart b/examples/pretty_node/lib/pretty_node_source.dart index 07f432e..6ad132b 100644 --- a/examples/pretty_node/lib/pretty_node_source.dart +++ b/examples/pretty_node/lib/pretty_node_source.dart @@ -4,5 +4,5 @@ const packageVersion = '1.0.0'; const packageSource = r''' -var S=Object.defineProperty;var D=Object.getOwnPropertySymbols;var F=Object.prototype.hasOwnProperty,w=Object.prototype.propertyIsEnumerable;var B=(e,t,n)=>t in e?S(e,t,{enumerable:true,configurable:true,writable:true,value:n}):e[t]=n,m=(e,t)=>{for(var n in t||(t={}))F.call(t,n)&&B(e,n,t[n]);if(D)for(var n of D(t))w.call(t,n)&&B(e,n,t[n]);return e};var p=["B","kB","MB","GB","TB","PB","EB","ZB","YB"],Y=["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],k=["b","kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],L=["b","kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],x=(e,t,n)=>{let s=e;return typeof t=="string"||Array.isArray(t)?s=e.toLocaleString(t,n):(t===true||n!==void 0)&&(s=e.toLocaleString(void 0,n)),s},E=e=>{if(typeof e=="number")return Math.log10(e);let t=e.toString(10);return t.length+Math.log10("0."+t.slice(0,15))},P=e=>typeof e=="number"?Math.log(e):E(e)*Math.log(10),U=(e,t)=>{if(typeof e=="number")return e/t;let n=e/BigInt(t),s=e%BigInt(t);return Number(n)+Number(s)/t};function g(e,t){if(typeof e!="bigint"&&!Number.isFinite(e))throw new TypeError(`Expected a finite number, got ${typeof e}: ${e}`);t=m({bits:false,binary:false,space:true},t);let n=t.bits?t.binary?L:k:t.binary?Y:p,s=t.space?" ":"";if(t.signed&&(typeof e=="number"?e===0:e===BigInt(0)))return ` 0${s}${n[0]}`;let c=e<0,b=c?"-":t.signed?"+":"";c&&(e=-e);let i;if(t.minimumFractionDigits!==void 0&&(i={minimumFractionDigits:t.minimumFractionDigits}),t.maximumFractionDigits!==void 0&&(i=m({maximumFractionDigits:t.maximumFractionDigits},i)),e<1){let a=x(e,t.locale,i);return b+a+s+n[0]}let o=Math.min(Math.floor(t.binary?P(e)/Math.log(1024):E(e)/3),n.length-1);e=U(e,(t.binary?1024:1e3)**o),i||(e=e.toPrecision(3));let f=x(Number(e),t.locale,i),y=n[o];return b+f+s+y}var T=e=>Number.isFinite(e)?e:0;function Z(e){return {days:Math.trunc(e/864e5),hours:Math.trunc(e/36e5%24),minutes:Math.trunc(e/6e4%60),seconds:Math.trunc(e/1e3%60),milliseconds:Math.trunc(e%1e3),microseconds:Math.trunc(T(e*1e3)%1e3),nanoseconds:Math.trunc(T(e*1e6)%1e3)}}function $(e){return {days:e/BigInt(86400000),hours:e/BigInt(3600000)%BigInt(24),minutes:e/BigInt(60000)%BigInt(60),seconds:e/BigInt(1000)%BigInt(60),milliseconds:e%BigInt(1000),microseconds:BigInt(0),nanoseconds:BigInt(0)}}function M(e){switch(typeof e){case "number":{if(Number.isFinite(e))return Z(e);break}case "bigint":return $(e)}throw new TypeError("Expected a finite number or bigint")}var A=e=>e===0||e===BigInt(0),C=(e,t)=>t===1||t===BigInt(1)?e:`${e}s`,G=1e-7,V=BigInt(24)*BigInt(60)*BigInt(60)*BigInt(1000);function N(e,t){let n=typeof e=="bigint";if(!n&&!Number.isFinite(e))throw new TypeError("Expected a finite number or bigint");t=m({},t);let s=e<0?"-":"";e=e<0?-e:e,t.colonNotation&&(t.compact=false,t.formatSubMilliseconds=false,t.separateMilliseconds=false,t.verbose=false),t.compact&&(t.unitCount=1,t.secondsDecimalDigits=0,t.millisecondsDecimalDigits=0);let c=[],b=(a,u)=>{let d=Math.floor(a*10**u+G);return (Math.round(d)/10**u).toFixed(u)},i=(a,u,d,r)=>{if(!((c.length===0||!t.colonNotation)&&A(a)&&!(t.colonNotation&&d==="m"))){if(r!=null||(r=String(a)),t.colonNotation){let l=r.includes(".")?r.split(".")[0].length:r.length,h=c.length>0?2:1;r="0".repeat(Math.max(0,h-l))+r;}else r+=t.verbose?" "+C(u,a):d;c.push(r);}},o=M(e),f=BigInt(o.days);if(t.hideYearAndDays?i(BigInt(f)*BigInt(24)+BigInt(o.hours),"hour","h"):(t.hideYear?i(f,"day","d"):(i(f/BigInt(365),"year","y"),i(f%BigInt(365),"day","d")),i(Number(o.hours),"hour","h")),i(Number(o.minutes),"minute","m"),!t.hideSeconds)if(t.separateMilliseconds||t.formatSubMilliseconds||!t.colonNotation&&e<1e3){let a=Number(o.seconds),u=Number(o.milliseconds),d=Number(o.microseconds),r=Number(o.nanoseconds);if(i(a,"second","s"),t.formatSubMilliseconds)i(u,"millisecond","ms"),i(d,"microsecond","\xB5s"),i(r,"nanosecond","ns");else {let l=u+d/1e3+r/1e6,h=typeof t.millisecondsDecimalDigits=="number"?t.millisecondsDecimalDigits:0,I=l>=1?Math.round(l):Math.ceil(l),_=h?l.toFixed(h):I;i(Number.parseFloat(_),"millisecond","ms",_);}}else {let a=(n?Number(e%V):e)/1e3%60,u=typeof t.secondsDecimalDigits=="number"?t.secondsDecimalDigits:1,d=b(a,u),r=t.keepDecimalsOnWholeSeconds?d:d.replace(/\.0+$/,"");i(Number.parseFloat(r),"second","s",r);}if(c.length===0)return s+"0"+(t.verbose?" milliseconds":"ms");let y=t.colonNotation?":":" ";return typeof t.unitCount=="number"&&(c=c.slice(0,Math.max(t.unitCount,1))),s+c.join(y)}var j=(e,t,n)=>{let s=g(t),c=new TextEncoder().encode(s);Dart.send_value(n,c);},z=(e,t,n)=>{let s=N(t),c=new TextEncoder().encode(s);Dart.send_value(n,c);},v={init:(...e)=>({}),functions:{make_pretty_bytes:j,make_pretty_ms:z}};export{v as default}; +var w=Object.defineProperty,F=Object.defineProperties;var k=Object.getOwnPropertyDescriptors;var B=Object.getOwnPropertySymbols;var Y=Object.prototype.hasOwnProperty,$=Object.prototype.propertyIsEnumerable;var D=(e,t,n)=>t in e?w(e,t,{enumerable:true,configurable:true,writable:true,value:n}):e[t]=n,m=(e,t)=>{for(var n in t||(t={}))Y.call(t,n)&&D(e,n,t[n]);if(B)for(var n of B(t))$.call(t,n)&&D(e,n,t[n]);return e},S=(e,t)=>F(e,k(t));var L=["B","kB","MB","GB","TB","PB","EB","ZB","YB"],P=["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],A=["b","kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit"],Z=["b","kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],E=(e,t,n)=>{let s=e;return typeof t=="string"||Array.isArray(t)?s=e.toLocaleString(t,n):(t===true||n!==void 0)&&(s=e.toLocaleString(void 0,n)),s},p=e=>{if(typeof e=="number")return Math.log10(e);let t=e.toString(10);return t.length+Math.log10(`0.${t.slice(0,15)}`)},U=e=>typeof e=="number"?Math.log(e):p(e)*Math.log(10),C=(e,t)=>{if(typeof e=="number")return e/t;let n=e/BigInt(t),s=e%BigInt(t);return Number(n)+Number(s)/t},T=(e,t)=>{if(t===void 0)return e;if(typeof t!="number"||!Number.isSafeInteger(t)||t<0)throw new TypeError(`Expected fixedWidth to be a non-negative integer, got ${typeof t}: ${t}`);return t===0?e:e.length{let{minimumFractionDigits:t,maximumFractionDigits:n}=e;if(!(t===void 0&&n===void 0))return S(m(m({},t!==void 0&&{minimumFractionDigits:t}),n!==void 0&&{maximumFractionDigits:n}),{roundingMode:"trunc"})};function g(e,t){if(typeof e!="bigint"&&!Number.isFinite(e))throw new TypeError(`Expected a finite number, got ${typeof e}: ${e}`);t=m({bits:false,binary:false,space:true,nonBreakingSpace:false},t);let n=t.bits?t.binary?Z:A:t.binary?P:L,s=t.space?t.nonBreakingSpace?"\xA0":" ":"",i=typeof e=="number"?e===0:e===BigInt(0);if(t.signed&&i){let l=` 0${s}${n[0]}`;return T(l,t.fixedWidth)}let y=e<0,c=y?"-":t.signed?"+":"";y&&(e=-e);let o=G(t),f;if(e<1){let l=E(e,t.locale,o);f=c+l+s+n[0];}else {let l=Math.min(Math.floor(t.binary?U(e)/Math.log(1024):p(e)/3),n.length-1);if(e=C(e,(t.binary?1024:1e3)**l),!o){let u=Math.max(3,Math.floor(e).toString().length);e=e.toPrecision(u);}let d=E(Number(e),t.locale,o),a=n[l];f=c+d+s+a;}return T(f,t.fixedWidth)}var I=e=>Number.isFinite(e)?e:0;function V(e){return {days:Math.trunc(e/864e5),hours:Math.trunc(e/36e5%24),minutes:Math.trunc(e/6e4%60),seconds:Math.trunc(e/1e3%60),milliseconds:Math.trunc(e%1e3),microseconds:Math.trunc(I(e*1e3)%1e3),nanoseconds:Math.trunc(I(e*1e6)%1e3)}}function j(e){return {days:e/BigInt(86400000),hours:e/BigInt(3600000)%BigInt(24),minutes:e/BigInt(60000)%BigInt(60),seconds:e/BigInt(1000)%BigInt(60),milliseconds:e%BigInt(1000),microseconds:BigInt(0),nanoseconds:BigInt(0)}}function M(e){switch(typeof e){case "number":{if(Number.isFinite(e))return V(e);break}case "bigint":return j(e)}throw new TypeError("Expected a finite number or bigint")}var z=e=>e===0||e===BigInt(0),K=(e,t)=>t===1||t===BigInt(1)?e:`${e}s`,O=1e-7,R=BigInt(24)*BigInt(60)*BigInt(60)*BigInt(1000);function N(e,t){let n=typeof e=="bigint";if(!n&&!Number.isFinite(e))throw new TypeError("Expected a finite number or bigint");t=m({},t);let s=e<0?"-":"";e=e<0?-e:e,t.colonNotation&&(t.compact=false,t.formatSubMilliseconds=false,t.separateMilliseconds=false,t.verbose=false),t.compact&&(t.unitCount=1,t.secondsDecimalDigits=0,t.millisecondsDecimalDigits=0);let i=[],y=(d,a)=>{let u=Math.floor(d*10**a+O);return (Math.round(u)/10**a).toFixed(a)},c=(d,a,u,r)=>{if(!((i.length===0||!t.colonNotation)&&z(d)&&!(t.colonNotation&&u==="m"))){if(r!=null||(r=String(d)),t.colonNotation){let b=r.includes(".")?r.split(".")[0].length:r.length,h=i.length>0?2:1;r="0".repeat(Math.max(0,h-b))+r;}else r+=t.verbose?" "+K(a,d):u;i.push(r);}},o=M(e),f=BigInt(o.days);if(t.hideYearAndDays?c(BigInt(f)*BigInt(24)+BigInt(o.hours),"hour","h"):(t.hideYear?c(f,"day","d"):(c(f/BigInt(365),"year","y"),c(f%BigInt(365),"day","d")),c(Number(o.hours),"hour","h")),c(Number(o.minutes),"minute","m"),!t.hideSeconds)if(t.separateMilliseconds||t.formatSubMilliseconds||!t.colonNotation&&e<1e3&&!t.subSecondsAsDecimals){let d=Number(o.seconds),a=Number(o.milliseconds),u=Number(o.microseconds),r=Number(o.nanoseconds);if(c(d,"second","s"),t.formatSubMilliseconds)c(a,"millisecond","ms"),c(u,"microsecond","\xB5s"),c(r,"nanosecond","ns");else {let b=a+u/1e3+r/1e6,h=typeof t.millisecondsDecimalDigits=="number"?t.millisecondsDecimalDigits:0,x=b>=1?Math.round(b):Math.ceil(b),_=h?b.toFixed(h):x;c(Number.parseFloat(_),"millisecond","ms",_);}}else {let d=(n?Number(e%R):e)/1e3%60,a=typeof t.secondsDecimalDigits=="number"?t.secondsDecimalDigits:1,u=y(d,a),r=t.keepDecimalsOnWholeSeconds?u:u.replace(/\.0+$/,"");c(Number.parseFloat(r),"second","s",r);}if(i.length===0)return s+"0"+(t.verbose?" milliseconds":"ms");let l=t.colonNotation?":":" ";return typeof t.unitCount=="number"&&(i=i.slice(0,Math.max(t.unitCount,1))),s+i.join(l)}var q=(e,t,n)=>{let s=g(t),i=new TextEncoder().encode(s);Dart.send_value(n,i);},H=(e,t,n)=>{let s=N(t),i=new TextEncoder().encode(s);Dart.send_value(n,i);},se={init:(...e)=>({}),functions:{make_pretty_bytes:q,make_pretty_ms:H}};export{se as default}; '''; diff --git a/examples/pretty_node/package-lock.json b/examples/pretty_node/package-lock.json new file mode 100644 index 0000000..69d97b8 --- /dev/null +++ b/examples/pretty_node/package-lock.json @@ -0,0 +1,1724 @@ +{ + "name": "pretty_node", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pretty_node", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "pretty-bytes": "^7.1.0", + "pretty-error": "^4.0.0", + "pretty-ms": "^9.3.0" + }, + "devDependencies": { + "@globe/runtime_types": "../../packages/globe_runtime_ts/runtime_types", + "@types/node": "^25.0.2", + "tsup": "^8.3.6", + "typescript": "^5.9.3" + } + }, + "../../packages/globe_runtime_ts": { + "name": "@globe/runtime_types", + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "../../packages/globe_runtime_ts/dart_source_generator": { + "name": "@globe/dart_source_generator", + "version": "1.0.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "glob": "^13.0.0", + "tsdown": "0.17.4", + "tslog": "^4.10.2", + "typescript": "^5.9.3" + }, + "bin": { + "globe-dart-source-generator": "dist/bin/generate.js" + }, + "devDependencies": { + "@types/node": "^25.0.2", + "@vitest/coverage-v8": "^4.0.15", + "vitest": "^4.0.15" + } + }, + "../../packages/globe_runtime_ts/runtime_types": { + "name": "@globe/runtime_types", + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", + "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", + "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", + "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", + "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", + "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", + "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", + "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", + "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", + "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", + "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", + "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", + "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", + "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", + "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", + "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", + "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", + "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", + "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", + "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", + "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", + "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", + "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", + "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", + "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", + "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", + "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@globe/runtime_types": { + "resolved": "../../packages/globe_runtime_ts/runtime_types", + "link": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.4.tgz", + "integrity": "sha512-PWU3Y92H4DD0bOqorEPp1Y0tbzwAurFmIYpjcObv5axGVOtcTlB0b2UKMd2echo08MgN7jO8WQZSSysvfisFSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.4.tgz", + "integrity": "sha512-Gw0/DuVm3rGsqhMGYkSOXXIx20cC3kTlivZeuaGt4gEgILivykNyBWxeUV5Cf2tDA2nPLah26vq3emlRrWVbng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.4.tgz", + "integrity": "sha512-+w06QvXsgzKwdVg5qRLZpTHh1bigHZIqoIUPtiqh05ZiJVUQ6ymOxaPkXTvRPRLH88575ZCRSRM3PwIoNma01Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.4.tgz", + "integrity": "sha512-EB4Na9G2GsrRNRNFPuxfwvDRDUwQEzJPpiK1vo2zMVhEeufZ1k7J1bKnT0JYDfnPC7RNZ2H5YNQhW6/p2QKATw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.4.tgz", + "integrity": "sha512-bldA8XEqPcs6OYdknoTMaGhjytnwQ0NClSPpWpmufOuGPN5dDmvIa32FygC2gneKK4A1oSx86V1l55hyUWUYFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.4.tgz", + "integrity": "sha512-3T8GPjH6mixCd0YPn0bXtcuSXi1Lj+15Ujw2CEb7dd24j9thcKscCf88IV7n76WaAdorOzAgSSbuVRg4C8V8Qw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.4.tgz", + "integrity": "sha512-UPMMNeC4LXW7ZSHxeP3Edv09aLsFUMaD1TSVW6n1CWMECnUIJMFFB7+XC2lZTdPtvB36tYC0cJWc86mzSsaviw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.4.tgz", + "integrity": "sha512-H8uwlV0otHs5Q7WAMSoyvjV9DJPiy5nJ/xnHolY0QptLPjaSsuX7tw+SPIfiYH6cnVx3fe4EWFafo6gH6ekZKA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.4.tgz", + "integrity": "sha512-BLRwSRwICXz0TXkbIbqJ1ibK+/dSBpTJqDClF61GWIrxTXZWQE78ROeIhgl5MjVs4B4gSLPCFeD4xML9vbzvCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.4.tgz", + "integrity": "sha512-6bySEjOTbmVcPJAywjpGLckK793A0TJWSbIa0sVwtVGfe/Nz6gOWHOwkshUIAp9j7wg2WKcA4Snu7Y1nUZyQew==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.4.tgz", + "integrity": "sha512-U0ow3bXYJZ5MIbchVusxEycBw7bO6C2u5UvD31i5IMTrnt2p4Fh4ZbHSdc/31TScIJQYHwxbj05BpevB3201ug==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.4.tgz", + "integrity": "sha512-iujDk07ZNwGLVn0YIWM80SFN039bHZHCdCCuX9nyx3Jsa2d9V/0Y32F+YadzwbvDxhSeVo9zefkoPnXEImnM5w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.4.tgz", + "integrity": "sha512-MUtAktiOUSu+AXBpx1fkuG/Bi5rhlorGs3lw5QeJ2X3ziEGAq7vFNdWVde6XGaVqi0LGSvugwjoxSNJfHFTC0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.4.tgz", + "integrity": "sha512-btm35eAbDfPtcFEgaXCI5l3c2WXyzwiE8pArhd66SDtoLWmgK5/M7CUxmUglkwtniPzwvWioBKKl6IXLbPf2sQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.4.tgz", + "integrity": "sha512-uJlhKE9ccUTCUlK+HUz/80cVtx2RayadC5ldDrrDUFaJK0SNb8/cCmC9RhBhIWuZ71Nqj4Uoa9+xljKWRogdhA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.4.tgz", + "integrity": "sha512-jjEMkzvASQBbzzlzf4os7nzSBd/cvPrpqXCUOqoeCh1dQ4BP3RZCJk8XBeik4MUln3m+8LeTJcY54C/u8wb3DQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.4.tgz", + "integrity": "sha512-lu90KG06NNH19shC5rBPkrh6mrTpq5kviFylPBXQVpdEu0yzb0mDgyxLr6XdcGdBIQTH/UAhDJnL+APZTBu1aQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.4.tgz", + "integrity": "sha512-dFDcmLwsUzhAm/dn0+dMOQZoONVYBtgik0VuY/d5IJUUb787L3Ko/ibvTvddqhb3RaB7vFEozYevHN4ox22R/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.4.tgz", + "integrity": "sha512-WvUpUAWmUxZKtRnQWpRKnLW2DEO8HB/l8z6oFFMNuHndMzFTJEXzaYJ5ZAmzNw0L21QQJZsUQFt2oPf3ykAD/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.4.tgz", + "integrity": "sha512-JGbeF2/FDU0x2OLySw/jgvkwWUo05BSiJK0dtuI4LyuXbz3wKiC1xHhLB1Tqm5VU6ZZDmAorj45r/IgWNWku5g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.4.tgz", + "integrity": "sha512-zuuC7AyxLWLubP+mlUwEyR8M1ixW1ERNPHJfXm8x7eQNP4Pzkd7hS3qBuKBR70VRiQ04Kw8FNfRMF5TNxuZq2g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.4.tgz", + "integrity": "sha512-Sbx45u/Lbb5RyptSbX7/3deP+/lzEmZ0BTSHxwxN/IMOZDZf8S0AGo0hJD5n/LQssxb5Z3B4og4P2X6Dd8acCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.2.tgz", + "integrity": "sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/bundle-require": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", + "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.18" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", + "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.1", + "@esbuild/android-arm": "0.27.1", + "@esbuild/android-arm64": "0.27.1", + "@esbuild/android-x64": "0.27.1", + "@esbuild/darwin-arm64": "0.27.1", + "@esbuild/darwin-x64": "0.27.1", + "@esbuild/freebsd-arm64": "0.27.1", + "@esbuild/freebsd-x64": "0.27.1", + "@esbuild/linux-arm": "0.27.1", + "@esbuild/linux-arm64": "0.27.1", + "@esbuild/linux-ia32": "0.27.1", + "@esbuild/linux-loong64": "0.27.1", + "@esbuild/linux-mips64el": "0.27.1", + "@esbuild/linux-ppc64": "0.27.1", + "@esbuild/linux-riscv64": "0.27.1", + "@esbuild/linux-s390x": "0.27.1", + "@esbuild/linux-x64": "0.27.1", + "@esbuild/netbsd-arm64": "0.27.1", + "@esbuild/netbsd-x64": "0.27.1", + "@esbuild/openbsd-arm64": "0.27.1", + "@esbuild/openbsd-x64": "0.27.1", + "@esbuild/openharmony-arm64": "0.27.1", + "@esbuild/sunos-x64": "0.27.1", + "@esbuild/win32-arm64": "0.27.1", + "@esbuild/win32-ia32": "0.27.1", + "@esbuild/win32-x64": "0.27.1" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fix-dts-default-cjs-exports": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz", + "integrity": "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.17", + "mlly": "^1.7.4", + "rollup": "^4.34.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/pretty-bytes": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-7.1.0.tgz", + "integrity": "sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup": { + "version": "4.53.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.4.tgz", + "integrity": "sha512-YpXaaArg0MvrnJpvduEDYIp7uGOqKXbH9NsHGQ6SxKCOsNAjZF018MmxefFUulVP2KLtiGw1UvZbr+/ekjvlDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.4", + "@rollup/rollup-android-arm64": "4.53.4", + "@rollup/rollup-darwin-arm64": "4.53.4", + "@rollup/rollup-darwin-x64": "4.53.4", + "@rollup/rollup-freebsd-arm64": "4.53.4", + "@rollup/rollup-freebsd-x64": "4.53.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.4", + "@rollup/rollup-linux-arm-musleabihf": "4.53.4", + "@rollup/rollup-linux-arm64-gnu": "4.53.4", + "@rollup/rollup-linux-arm64-musl": "4.53.4", + "@rollup/rollup-linux-loong64-gnu": "4.53.4", + "@rollup/rollup-linux-ppc64-gnu": "4.53.4", + "@rollup/rollup-linux-riscv64-gnu": "4.53.4", + "@rollup/rollup-linux-riscv64-musl": "4.53.4", + "@rollup/rollup-linux-s390x-gnu": "4.53.4", + "@rollup/rollup-linux-x64-gnu": "4.53.4", + "@rollup/rollup-linux-x64-musl": "4.53.4", + "@rollup/rollup-openharmony-arm64": "4.53.4", + "@rollup/rollup-win32-arm64-msvc": "4.53.4", + "@rollup/rollup-win32-ia32-msvc": "4.53.4", + "@rollup/rollup-win32-x64-gnu": "4.53.4", + "@rollup/rollup-win32-x64-msvc": "4.53.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tsup": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz", + "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-require": "^5.1.0", + "cac": "^6.7.14", + "chokidar": "^4.0.3", + "consola": "^3.4.0", + "debug": "^4.4.0", + "esbuild": "^0.27.0", + "fix-dts-default-cjs-exports": "^1.0.0", + "joycon": "^3.1.1", + "picocolors": "^1.1.1", + "postcss-load-config": "^6.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.34.8", + "source-map": "^0.7.6", + "sucrase": "^3.35.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.11", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "license": "MIT" + } + } +} diff --git a/examples/pretty_node/package.json b/examples/pretty_node/package.json index b55f8b7..64b7cf1 100644 --- a/examples/pretty_node/package.json +++ b/examples/pretty_node/package.json @@ -7,13 +7,13 @@ "author": "", "license": "ISC", "dependencies": { - "pretty-bytes": "^7.0.0", - "pretty-ms": "^9.2.0" + "pretty-bytes": "^7.1.0", + "pretty-ms": "^9.3.0" }, "devDependencies": { "@globe/runtime_types": "workspace:*", - "fs": "catalog:", - "path": "catalog:", + "@globe/dart_source_generator": "workspace:*", + "@types/node": "catalog:", "tsup": "catalog:", "typescript": "catalog:" } diff --git a/examples/pretty_node/pubspec.yaml b/examples/pretty_node/pubspec.yaml index e7ff1dd..85d28b0 100644 --- a/examples/pretty_node/pubspec.yaml +++ b/examples/pretty_node/pubspec.yaml @@ -1,12 +1,13 @@ name: pretty_node version: 1.0.0 description: A Dart package that uses Node.js modules. +publish_to: none environment: sdk: ^3.4.0 dependencies: - globe_runtime: ^1.0.7 + globe_runtime: "^1.0.8" dev_dependencies: diff --git a/examples/pretty_node/tsconfig.json b/examples/pretty_node/tsconfig.json index 9275529..cce220b 100644 --- a/examples/pretty_node/tsconfig.json +++ b/examples/pretty_node/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "target": "es2016", "module": "commonjs", - "types": ["@globe/runtime_types"], + "lib": ["ES2016"], + "types": ["@globe/runtime_types", "node"], "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, diff --git a/packages/globe_runtime/README.md b/packages/globe_runtime/README.md index 8a70cc5..bee864f 100644 --- a/packages/globe_runtime/README.md +++ b/packages/globe_runtime/README.md @@ -480,18 +480,151 @@ In your JavaScript modules, you have access to: Globe Runtime supports using NPM packages through a bundling approach. This allows you to use any JavaScript library in your Dart applications. -### Why Bundle Instead of FileModule? +### Recommended Approach: Using @globe/dart_source_generator (Easiest) -When using NPM packages, you **cannot** use `FileModule` directly because: +The **recommended way** to create Globe Runtime SDKs is using the `@globe/dart_source_generator` CLI with `@globe/runtime_types`. This provides: -1. **Module Resolution**: Globe Runtime's internal module resolver expects proper `file://` URLs, but npm packages use different import mechanisms -2. **Dependency Management**: NPM packages have their own dependencies that need to be resolved and bundled together -3. **Browser Environment**: Globe Runtime runs in a browser-like environment, not Node.js, so packages need to be bundled for browser compatibility -4. **Import/Export Compatibility**: ES modules and CommonJS modules need to be properly transformed for the runtime environment +- **Type-safe SDK definitions** with full TypeScript support +- **Automatic bundling** of your code with all dependencies +- **Seamless Dart integration** with generated wrapper classes +- **Hot reload support** in watch mode during development -The bundling approach ensures all dependencies are included and properly formatted for Globe Runtime. +### Example -### Approach 1: Using esbuild (JavaScript - Simpler) +#### Step 1: Set up your TypeScript SDK + +Create a new directory for your SDK and initialize it: + +```bash +mkdir my_sdk +cd my_sdk +npm init -y +npm install @globe/runtime_types @globe/dart_source_generator -D +``` + +#### Step 2: Define your SDK in TypeScript + +Create `src/sdk.ts`. +Note: You can create multiple SDKs in the same project but not in the same file. + +```typescript +import { defineSdk, returnString, streamString } from "@globe/runtime_types"; + +type ModuleState = { + apiUrl: string; + timeout: number; +}; + +const fetchUsers = streamString( + async (state: ModuleState, callbackId: number) => { + try { + const url = `${state.apiUrl}/users`; + const response = await fetch(url, { + signal: AbortSignal.timeout(state.timeout) + }); + + for await (const chunk of response.body!.values()) { + Dart.stream_value(callbackId, chunk); + } + + Dart.stream_value_end(callbackId); + } catch (error) { + Dart.send_error(callbackId, `Stream failed: ${error.message}`); + } + } +); + +const calculatePrice = returnInt( + (state: ModuleState, quantity: number, price: number, callbackId: number) => { + const total = quantity * price; + Dart.send_value(callbackId, new TextEncoder().encode(total.toString())); + } +); + +export default defineSdk({ + init(apiUrl: string = "https://api.example.com", timeout: number = 5000): ModuleState { + return { apiUrl, timeout }; + }, + functions: { + fetchUsers, + calculatePrice, + }, +}); +``` + +#### Step 3: Generate Dart source files + +Run the generator: + +```bash +npx @globe/dart_source_generator --files src/sdk.ts --output lib/ +``` + +This generates `lib/sdk_source.dart` containing the bundled JavaScript code. + +#### Step 4: Use in your Dart project + +Add to your `pubspec.yaml`: + +```yaml +dependencies: + globe_runtime: ^1.0.7 +``` + +Then use in your Dart code: + +Create `lib/sdk_access.dart`: + +```dart +import 'dart:async'; +import 'package:your_package/sdk_source.dart'; + +void main() async { + // Create an instance of your SDK with initialization parameters + final sdk = await Sdk.create( + apiUrl: 'https://api.custom.com', + timeout: 10000, + ); + + // Call single-value functions (returns a Future) + final price = await sdk.calculatePrice(10, 99); + print('Total Price: $price'); + + // Call streaming functions (returns a Stream) + final userStream = await sdk.fetchUsers(); + + final completer = Completer(); + userStream.listen((user) { + print('User: $user'); + }, onDone: completer.complete); + + await completer.future; + + // Clean up when done + sdk.dispose(); +} +``` + +#### Final Project structure + +``` +my_sdk/ +├── src/ +│ └── sdk.ts +├── lib/ +│ └── sdk_access.dart +│ └── sdk_source.dart +├── pubspec.yaml +├── package.json +``` + +The `@globe/dart_source_generator` automatically generates the SDK wrapper class with type-safe methods that handle all the Dart FFI interop boilerplate. You simply call methods, with type-safe parameters, and get properly typed `Future` or `Stream` objects back. + +For more details, see the [@globe/dart_source_generator documentation](https://github.com/invertase/globe_runtime/tree/main/packages/globe_runtime_ts/dart_source_generator/README.md) and [@globe/runtime_types documentation](https://github.com/invertase/globe_runtime/tree/main/packages/globe_runtime_ts/runtime_types/README.md). + +--- + +### Alternative Approach 1: Using esbuild (JavaScript - Simpler) #### Step 1: Create package.json @@ -633,7 +766,7 @@ void main() async { } ``` -### Approach 2: Using tsup (TypeScript - Recommended) +### Alternative Approach 2: Using tsup (TypeScript) #### Step 1: Create package.json @@ -786,7 +919,7 @@ void main() async { ### Why This Approach Works -1. **Bundling**: `tsup` bundles all NPM dependencies into a single JavaScript file +1. **Bundling**: Bundlers like `tsup` or `esbuild` bundle all NPM dependencies into a single JavaScript file 2. **TypeScript Support**: Full type safety and IntelliSense 3. **No external dependencies**: The bundled file contains everything needed 4. **InlinedModule**: Uses the bundled code directly, avoiding file path and module resolution issues diff --git a/packages/globe_runtime_ts/dart_source_generator/.gitignore b/packages/globe_runtime_ts/dart_source_generator/.gitignore new file mode 100644 index 0000000..3b8b602 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/.gitignore @@ -0,0 +1,2 @@ +dist/ +coverage/ \ No newline at end of file diff --git a/packages/globe_runtime_ts/dart_source_generator/LICENSE b/packages/globe_runtime_ts/dart_source_generator/LICENSE new file mode 100644 index 0000000..6845152 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2023-present Invertase Limited + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/packages/globe_runtime_ts/dart_source_generator/README.md b/packages/globe_runtime_ts/dart_source_generator/README.md new file mode 100644 index 0000000..2e19f1b --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/README.md @@ -0,0 +1,402 @@ +# Globe Dart Source Generator (@globe/dart_source_generator) + +A powerful code generation tool that transforms TypeScript/JavaScript source files into Dart-compatible source files. This package bundles your TypeScript code with all dependencies and generates type-safe Dart source files for seamless integration with Dart/Flutter projects. + +## Overview + +The tool is used to generate the Dart source files for use with the Globe runtime. For more information, see the [Globe Runtime](https://github.com/globe-runtime/globe_runtime). + +Your TypeScript files should export an SDK object that is used to generate the Dart source files. To do this, you should use the wrappers from the [`@globe/runtime_types`](https://github.com/globe-runtime/globe_runtime_ts) package. + +## Features + +- **Automatic Bundling**: Bundles TypeScript/JavaScript files with all dependencies into single, minified outputs +- **Type Preservation**: Generates TypeScript declaration files (.d.ts) and converts them to Dart-compatible formats +- **Documentation Transfer**: Function JSDoc comments and parameter names are preserved from TypeScript to Dart +- **Init Documentation**: `init` function documentation and parameters are transferred to the Dart `create` factory + +``` +Notes: +- The `init` function is optional. +- The `functions` object is required. +- To preserve documentation all documentation must be in JSDoc format and declared within the defineSdk function. +``` +- **Batch Processing**: Process multiple files in a single run +- **Watch Mode**: Monitor files for changes and automatically regenerate +- **Flexible Input**: Accept individual files or scan entire directories +- **Tree-shaking**: Removes unused code to minimize output size +- **Verbose Logging**: Optional detailed logging for debugging + +## Installation + +### Prerequisites + +You need to have both the CLI installed on your development system and the Globe runtime package in your Dart/Flutter project. + +**Install the CLI:** +```bash +npm install -g @globe/dart_source_generator +# or use npx to run without installing globally +``` + +**Add Globe runtime to your Dart/Flutter project:** +```bash +flutter pub add globe_runtime +# or for Dart projects +dart pub add globe_runtime +``` + +## Usage + +### Via Command Line + +The generator is available as an executable that can be run directly: + +```bash +npx @globe/dart_source_generator [options] +``` + +### Basic Examples + +**Generate from specific files:** +```bash +npx @globe/dart_source_generator --files src/utils.ts src/helpers.ts --output dist/ +``` + +**Generate from a directory:** +```bash +npx @globe/dart_source_generator --input src/ --output dist/ +``` + +**Watch mode for development:** +```bash +npx @globe/dart_source_generator --input src/ --output dist/ --watch +``` + +**Enable verbose logging:** +```bash +npx @globe/dart_source_generator --files src/index.ts --output dist/ --verbose +``` + +### Command Options + +| Option | Type | Description | +|--------|------|-------------| +| `--files ` | string (multiple) | List of input files to process (can be repeated) | +| `--input ` | string | Input directory to scan for .ts and .js files | +| `--output ` | string | Output directory for generated Dart files (default: current directory) | +| `--watch` | boolean | Watch input files for changes and regenerate automatically | +| `--verbose` | boolean | Enable detailed logging output | +| `--help` | boolean | Display help message | + +## How It Works + +1. **Input**: Accepts TypeScript or JavaScript files as input +2. **Bundling**: Uses `tsdown` to bundle your code with all dependencies, applying tree-shaking and minification +3. **Extraction**: Extracts the bundled ESM output and TypeScript declarations +4. **Dart Generation**: Converts the bundled code and type information into Dart-compatible source files +5. **Output**: Generates `_source.dart` files in your specified output directory. The output filename is a snake_case version of the TypeScript filename (e.g., `my-sdk.ts` or `mySdk.ts` -> `my_sdk_source.dart`). + +## Example Workflow + +Your TypeScript SDK should export a default object created with `defineSdk()` that includes initialization and function definitions: + +#### TypeScript Input (`src/sdk.ts`) + +```typescript +import { defineSdk, returnInt, streamMap } from "@globe/runtime_types"; + +type ModuleState = { + apiUrl: string; + timeout: number; +}; + +export default defineSdk({ + /** + * Initialize the SDK with authentication credentials + * + * This sets up the SDK with your API key and configures the timeout + * for all network requests. + * + * @param apiUrl - The base URL for API requests + * @param timeout - Request timeout in milliseconds + */ + init( + apiUrl: string = "https://api.example.com", + timeout: number = 5000 + ): ModuleState { + return { apiUrl, timeout }; + }, + functions: { + /** + * Streams user information from the API + * + * This function retrieves user information based on the provided user ID. + * + * @param userId - The unique identifier for the user + * @returns The user's information as a map of key-value pairs in a stream. + */ + fetch_user: streamMap( + async (state: ModuleState, userId: string, callbackId: number) => { + try { + const url = `${state.apiUrl}/user/${userId}`; + const response = await fetch(url, { + signal: AbortSignal.timeout(state.timeout), + }); + + for await (const chunk of response.body!.values()) { + Dart.stream_value(callbackId, chunk); + } + + Dart.stream_value_end(callbackId); + } catch (error) { + Dart.send_error( + callbackId, + `Stream failed: ${(error as Error).message}` + ); + } + } + ), + + /** + * Calculates the total price based on quantity and price per unit + * + * @param quantity - The number of units + * @param price - The price per unit + * @returns The total price + */ + calculate_price: returnInt( + ( + state: ModuleState, + quantity: number, + price: number, + callbackId: number + ) => { + const total = quantity * price; + Dart.send_value(callbackId, new TextEncoder().encode(total.toString())); + } + ), + }, +}); +``` + +#### Generate Dart Source + +```bash +npx @globe/dart_source_generator --files src/sdk.ts --output lib/generated/ +``` + +The generator will create a Dart file for each TypeScript file in the specified output directory. + +The generated Dart file would be (`lib/generated/sdk_source.dart`): + +```dart +// GENERATED FILE — DO NOT MODIFY BY HAND +// This file was generated from @globe/dart_source_generator +// ignore_for_file: unused_import + +import 'dart:async'; +import 'dart:convert'; +import 'package:globe_runtime/globe_runtime.dart'; + +/// Package version +const packageVersion = '1.0.0'; + +/// Package source code +const packageSource = r''' +...(minified code) +'''; + +/// {@template Sdk} +/// Sdk class +/// {@endtemplate} +class Sdk { + /// {@macro Sdk} + Sdk._(this._module); + + /// Module instance + final Module _module; + + /// Initialize the SDK with authentication credentials + /// + /// This sets up the SDK with your API key and configures the timeout for all + /// network requests. + /// + /// **Parameters:** + /// * [apiUrl]: The base URL for API requests + /// * [timeout]: Request timeout in milliseconds + static Future create({String? apiUrl, num? timeout}) async { + const module = InlinedModule( + name: 'Sdk', + sourceCode: packageSource, + ); + + await module.register(args: [apiUrl?.toFFIType, timeout?.toFFIType]); + return Sdk._(module); + } + + /// Disposes of the runtime instance + void dispose() { + GlobeRuntime.instance.dispose(); + } + + /// Streams user information from the API + /// + /// This function retrieves user information based on the provided user ID. + /// + /// **Parameters:** + /// * [userId]: The unique identifier for the user + /// + /// **Returns:** The user's information as a map of key-value pairs in a stream. + Stream> fetchUser(String userId) { + final controller = StreamController>(); + + _module.callFunction( + 'fetch_user', + args: [userId.toFFIType], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + if (data.hasData()) { + final value = data.data.unpack(); + controller.add(value as Map); + } + + if (data.done) { + controller.close(); + return true; + } + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + + /// Calculates the total price based on quantity and price per unit + /// + /// **Parameters:** + /// * [quantity]: The number of units + /// * [price]: The price per unit + /// + /// **Returns:** The total price + Future calculatePrice(num quantity, num price) async { + final completer = Completer(); + + _module.callFunction( + 'calculate_price', + args: [quantity.toFFIType, price.toFFIType], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + final value = data.data.unpack(); + completer.complete(value as num); + } + return true; + }, + ); + + return completer.future; + } +} +``` + + +#### Output + +``` +lib/generated/ +└── sdk_source.dart +``` + +The generated Dart file contains the bundled, minified JavaScript code along with type information extracted from your TypeScript definitions, making it ready to use in your Dart/Flutter projects with the Globe runtime. + +## Dart Usage Example + +Once you've generated your Dart source files, you can use them in your Dart/Flutter project: + +```dart +import 'dart:async'; +import 'package:your_package/generated/sdk_source.dart'; + +void main() async { + // Create an instance of your SDK with initialization parameters + final sdk = await Sdk.create( + apiUrl: 'https://api.custom.com', + timeout: 10000, + ); + + // Call single-value functions (returns a Future) + final price = await sdk.calculatePrice(10, 99); + print('Total Price: $price'); + + // Call streaming functions (returns a Stream) + final userStream = await sdk.fetchUser('123'); + + final completer = Completer(); + userStream.listen((user) { + print('User: $user'); + }, onDone: completer.complete); + + await completer.future; + + // Clean up when done + sdk.dispose(); +} +``` + +### Key Concepts + +- **Initialization**: Call `.create()` with any parameters defined in your SDK's `init()` function +- **Single Values**: Functions wrapped with `returnString`, `returnInt`, etc. return `Future` +- **Streams**: Functions wrapped with `streamString`, `streamInt`, etc. return `Future>` +- **Cleanup**: Call `.dispose()` to clean up resources when finished + +For more detailed examples, see the [Globe Runtime documentation](https://github.com/globe-runtime/globe_runtime). + +## Processing Multiple Files + +Each input file is processed independently with its own dependency bundle. This ensures that each generated Dart file is self-contained and includes all necessary dependencies. + +```bash +npx @globe/dart_source_generator \ + --files src/api.ts src/utils.ts src/validators.ts \ + --output lib/generated/ +``` + +This generates: +- `lib/generated/api_source.dart` +- `lib/generated/utils_source.dart` +- `lib/generated/validators_source.dart` + +## Development Mode + +Use watch mode while developing to automatically regenerate files as you make changes: + +```bash +npx @globe/dart_source_generator --input src/ --output lib/generated/ --watch +``` + +## Troubleshooting + +**"File does not exist" error**: Verify that all file paths are correct and relative to where you're running the command. + +**No input files found**: Ensure you're using either `--files` or `--input`. At least one must be provided. + +**Enable verbose output**: Use `--verbose` to see detailed logs about the bundling and generation process: +```bash +npx @globe/dart_source_generator --files src/index.ts --output dist/ --verbose +``` + +## Version + +The generator automatically includes version information from your package in the generated Dart files. + +## License + +See LICENSE for details. \ No newline at end of file diff --git a/packages/globe_runtime_ts/dart_source_generator/bin/generate.ts b/packages/globe_runtime_ts/dart_source_generator/bin/generate.ts new file mode 100644 index 0000000..a58d316 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/bin/generate.ts @@ -0,0 +1,214 @@ +#!/usr/bin/env node +import { existsSync } from "fs"; +import { mkdtemp, rm } from "fs/promises"; +import { glob } from "glob"; +import { tmpdir } from "os"; +import { basename, dirname, join, relative, resolve } from "path"; +import { snakeCase } from "text-case"; +import { build, defineConfig } from "tsdown"; +import { ILogObj, Logger } from "tslog"; +import { parseArgs } from "util"; +import { version } from "../package.json"; +import { generateDartSourceFile } from "../src/index"; + +// Helper to bundle and generate +async function run() { + const { values } = parseArgs({ + options: { + files: { + type: "string", + multiple: true, + }, + input: { + type: "string", + }, + output: { + type: "string", + default: ".", + }, + watch: { + type: "boolean", + }, + verbose: { + type: "boolean", + default: false, + }, + help: { + type: "boolean", + }, + }, + }); + + if (values.help) { + console.log(` +Usage: npx @globe/dart_source_generator [generate] [options] + +Options: + --files List of input files (can be repeated) + --input Input directory to scan for .ts files + --output Output directory (default: .) + --watch Watch for changes and re-run + --verbose Enable verbose logging + --help Show this help message +`); + process.exit(0); + } + + // Set up logging + const minLevel = values.verbose + ? 1 // trace + : 3; // info + const hideLogPositionForProduction = values.verbose ? false : true; + + const logger: Logger = new Logger({ + minLevel, + hideLogPositionForProduction, + // hide all preceding info if not verbose + prettyLogTemplate: values.verbose ? undefined : "", + }); + + const inputFiles: string[] = []; + + if (values.files) { + // Filter for .ts and .js files, and ensure they exist. + const files = values.files.filter((f) => { + const exists = existsSync(f); + if (!exists) { + console.error(`File does not exist: ${f}`); + return false; + } + return f.endsWith(".ts") || f.endsWith(".js"); + }); + inputFiles.push(...files); + } + + if (values.input) { + const folder = values.input; + // Ensure node_modules folder is not included. + const files = await glob(`${folder}/**/*.[t,j]s`, { + ignore: `${folder}/**/node_modules/**`, + }); + inputFiles.push(...files); + } + + if (inputFiles.length === 0) { + console.error("No input files provided. Use --files or --input."); + process.exit(1); + } else { + logger.debug("Input files found:", inputFiles); + } + + // Create temp dir + const tempDir = await mkdtemp(join(tmpdir(), "globe-gen-")); + + // Process each file individually. + // This is to ensure every file is bundled with its own dependencies fully. + for (const file of inputFiles) { + const filePath = resolve(file); + logger.debug("Processing file:", filePath); + // Get file folder path + const fileFolder = values.input ?? dirname(filePath); + logger.debug("File folder:", fileFolder); + + // Get relative path of input file from file folder + const relativePath = relative(fileFolder, filePath); + logger.debug("Relative path:", relativePath); + + const relativeName = relativePath.replace(/\.[t,j]s$/, ""); + logger.debug("Relative name:", relativeName); + + // Use basename as key. + const name = basename(relativeName); + logger.debug("Name:", name); + + // Get output folder + const outputFolder = resolve(values.output!); + logger.debug("Output folder:", outputFolder); + + // Display the relative path to the file being processed + logger.info(`\x1b[34mProcessing\x1b[0m \x1b[32m${relativePath}\x1b[0m`); + + await new Promise(async (resolveGenerate, rejectGenerate) => { + const config = defineConfig({ + entry: { [name]: file }, + outDir: tempDir, + format: ["esm"], + minify: true, + sourcemap: false, + unbundle: false, + treeshake: true, + clean: true, + dts: true, + noExternal: [/.*/], + watch: values.watch, + platform: "browser", + logLevel: values.verbose ? "info" : "warn", + onSuccess: async () => { + const { readdir } = await import("fs/promises"); + const files = await readdir(tempDir, { recursive: true }); + const filesSet = new Set(files); + + let sourceFile = join(tempDir, `${name}.mjs`); + let dtsFile = join(tempDir, `${name}.d.mts`); + + if (!filesSet.has(`${name}.mjs`) && filesSet.has(`${name}.js`)) { + sourceFile = join(tempDir, `${name}.js`); + } + + if (!filesSet.has(`${name}.d.mts`) && filesSet.has(`${name}.d.ts`)) { + dtsFile = join(tempDir, `${name}.d.ts`); + } + + const outputFolderPath = dirname(join(outputFolder, relativeName)); + logger.debug("Output folder path:", outputFolderPath); + + const outputBaseName = snakeCase(basename(relativeName)); + const outputPath = join( + outputFolderPath, + `${outputBaseName}_source.dart` + ); + logger.debug("Output path:", outputPath); + + try { + const success = generateDartSourceFile({ + jsSourcePath: sourceFile, + dtsFilePath: dtsFile, + outputPath: outputPath, + fileName: name, + version: version, + }); + + if (!success) { + rejectGenerate(`Failed to generate Dart source for ${name}`); + return; + } + + const relativePath = relative(outputFolder, outputPath); + logger.info( + `\x1b[34mWROTE\x1b[0m \x1b[32m${relativePath}\x1b[0m\n` + ); + + // Resolve the promise + resolveGenerate(); + } catch (e) { + logger.error(`Failed to generate Dart source for ${name}:`, e); + } + }, + }); + + await build(config); + }); + } + + // Cleanup + await rm(tempDir, { recursive: true, force: true }); + if (!values.watch) { + process.exit(0); + } +} + +// Generate the source files +run().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/packages/globe_runtime_ts/dart_source_generator/package-lock.json b/packages/globe_runtime_ts/dart_source_generator/package-lock.json new file mode 100644 index 0000000..567290f --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/package-lock.json @@ -0,0 +1,2681 @@ +{ + "name": "@globe/dart_source_generator", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@globe/dart_source_generator", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "glob": "^13.0.0", + "text-case": "^1.2.9", + "tsdown": "^0.18.2", + "tslog": "^4.10.2", + "typescript": "^5.9.3" + }, + "bin": { + "globe-dart-source-generator": "dist/bin/generate.js" + }, + "devDependencies": { + "@types/node": "^25.0.3", + "@vitest/coverage-v8": "^4.0.16", + "vitest": "^4.0.16" + } + }, + "../runtime_types": { + "name": "@globe/runtime_types", + "version": "1.0.3", + "extraneous": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.0.tgz", + "integrity": "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.103.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.103.0.tgz", + "integrity": "sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", + "license": "MIT", + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.55.tgz", + "integrity": "sha512-5cPpHdO+zp+klznZnIHRO1bMHDq5hS9cqXodEKAaa/dQTPDjnE91OwAsy3o1gT2x4QaY8NzdBXAvutYdaw0WeA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.55.tgz", + "integrity": "sha512-l0887CGU2SXZr0UJmeEcXSvtDCOhDTTYXuoWbhrEJ58YQhQk24EVhDhHMTyjJb1PBRniUgNc1G0T51eF8z+TWw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.55.tgz", + "integrity": "sha512-d7qP2AVYzN0tYIP4vJ7nmr26xvmlwdkLD/jWIc9Z9dqh5y0UGPigO3m5eHoHq9BNazmwdD9WzDHbQZyXFZjgtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.55.tgz", + "integrity": "sha512-j311E4NOB0VMmXHoDDZhrWidUf7L/Sa6bu/+i2cskvHKU40zcUNPSYeD2YiO2MX+hhDFa5bJwhliYfs+bTrSZw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.55.tgz", + "integrity": "sha512-lAsaYWhfNTW2A/9O7zCpb5eIJBrFeNEatOS/DDOZ5V/95NHy50g4b/5ViCqchfyFqRb7MKUR18/+xWkIcDkeIw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.55.tgz", + "integrity": "sha512-2x6ffiVLZrQv7Xii9+JdtyT1U3bQhKj59K3eRnYlrXsKyjkjfmiDUVx2n+zSyijisUqD62fcegmx2oLLfeTkCA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.55.tgz", + "integrity": "sha512-QbNncvqAXziya5wleI+OJvmceEE15vE4yn4qfbI/hwT/+8ZcqxyfRZOOh62KjisXxp4D0h3JZspycXYejxAU3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.55.tgz", + "integrity": "sha512-YZCTZZM+rujxwVc6A+QZaNMJXVtmabmFYLG2VGQTKaBfYGvBKUgtbMEttnp/oZ88BMi2DzadBVhOmfQV8SuHhw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.55.tgz", + "integrity": "sha512-28q9OQ/DDpFh2keS4BVAlc3N65/wiqKbk5K1pgLdu/uWbKa8hgUJofhXxqO+a+Ya2HVTUuYHneWsI2u+eu3N5Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.55.tgz", + "integrity": "sha512-LiCA4BjCnm49B+j1lFzUtlC+4ZphBv0d0g5VqrEJua/uyv9Ey1v9tiaMql1C8c0TVSNDUmrkfHQ71vuQC7YfpQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.55.tgz", + "integrity": "sha512-nZ76tY7T0Oe8vamz5Cv5CBJvrqeQxwj1WaJ2GxX8Msqs0zsQMMcvoyxOf0glnJlxxgKjtoBxAOxaAU8ERbW6Tg==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.55.tgz", + "integrity": "sha512-TFVVfLfhL1G+pWspYAgPK/FSqjiBtRKYX9hixfs508QVEZPQlubYAepHPA7kEa6lZXYj5ntzF87KC6RNhxo+ew==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.55.tgz", + "integrity": "sha512-j1WBlk0p+ISgLzMIgl0xHp1aBGXenoK2+qWYc/wil2Vse7kVOdFq9aeQ8ahK6/oxX2teQ5+eDvgjdywqTL+daA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.55.tgz", + "integrity": "sha512-vajw/B3qoi7aYnnD4BQ4VoCcXQWnF0roSwE2iynbNxgW4l9mFwtLmLmUhpDdcTBfKyZm1p/T0D13qG94XBLohA==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz", + "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz", + "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.54.0.tgz", + "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz", + "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz", + "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz", + "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz", + "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz", + "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz", + "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz", + "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz", + "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz", + "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz", + "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz", + "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz", + "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz", + "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz", + "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz", + "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz", + "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz", + "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz", + "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz", + "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz", + "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.16.tgz", + "integrity": "sha512-2rNdjEIsPRzsdu6/9Eq0AYAzYdpP6Bx9cje9tL3FE5XzXRQF1fNU9pe/1yE8fCrS0HD+fBtt6gLPh6LI57tX7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.0.16", + "ast-v8-to-istanbul": "^0.3.8", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.1", + "obug": "^2.1.1", + "std-env": "^3.10.0", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.0.16", + "vitest": "4.0.16" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.16.tgz", + "integrity": "sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.16", + "@vitest/utils": "4.0.16", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.16.tgz", + "integrity": "sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.16", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.16.tgz", + "integrity": "sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.16.tgz", + "integrity": "sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.16", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.16.tgz", + "integrity": "sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.16", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.16.tgz", + "integrity": "sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.16.tgz", + "integrity": "sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.16", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.8.tgz", + "integrity": "sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^9.0.1" + } + }, + "node_modules/birpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.1.tgz", + "integrity": "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" + }, + "node_modules/dts-resolver": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/dts-resolver/-/dts-resolver-2.1.3.tgz", + "integrity": "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==", + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "oxc-resolver": ">=11.0.0" + }, + "peerDependenciesMeta": { + "oxc-resolver": { + "optional": true + } + } + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hookable": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-6.0.1.tgz", + "integrity": "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==", + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-without-cache": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/import-without-cache/-/import-without-cache-0.2.5.tgz", + "integrity": "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==", + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", + "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-beta.55", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.55.tgz", + "integrity": "sha512-r8Ws43aYCnfO07ao0SvQRz4TBAtZJjGWNvScRBOHuiNHvjfECOJBIqJv0nUkL1GYcltjvvHswRilDF1ocsC0+g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@oxc-project/types": "=0.103.0", + "@rolldown/pluginutils": "1.0.0-beta.55" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.55", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.55", + "@rolldown/binding-darwin-x64": "1.0.0-beta.55", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.55", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.55", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.55", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.55", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.55", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.55", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.55", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.55", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.55", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.55" + } + }, + "node_modules/rolldown-plugin-dts": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/rolldown-plugin-dts/-/rolldown-plugin-dts-0.19.2.tgz", + "integrity": "sha512-KbP0cnnjD1ubnyklqy6GCahvUsOrPFH4i+RTX6bNpyvh+jUsaxY01e9mLOU2NsGzQkJS/q4hbCbdcQoAmSWIYg==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.28.5", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "ast-kit": "^2.2.0", + "birpc": "^4.0.0", + "dts-resolver": "^2.1.3", + "get-tsconfig": "^4.13.0", + "obug": "^2.1.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@ts-macro/tsc": "^0.3.6", + "@typescript/native-preview": ">=7.0.0-dev.20250601.1", + "rolldown": "^1.0.0-beta.55", + "typescript": "^5.0.0", + "vue-tsc": "~3.2.0" + }, + "peerDependenciesMeta": { + "@ts-macro/tsc": { + "optional": true + }, + "@typescript/native-preview": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/rollup": { + "version": "4.54.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz", + "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.54.0", + "@rollup/rollup-android-arm64": "4.54.0", + "@rollup/rollup-darwin-arm64": "4.54.0", + "@rollup/rollup-darwin-x64": "4.54.0", + "@rollup/rollup-freebsd-arm64": "4.54.0", + "@rollup/rollup-freebsd-x64": "4.54.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", + "@rollup/rollup-linux-arm-musleabihf": "4.54.0", + "@rollup/rollup-linux-arm64-gnu": "4.54.0", + "@rollup/rollup-linux-arm64-musl": "4.54.0", + "@rollup/rollup-linux-loong64-gnu": "4.54.0", + "@rollup/rollup-linux-ppc64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-gnu": "4.54.0", + "@rollup/rollup-linux-riscv64-musl": "4.54.0", + "@rollup/rollup-linux-s390x-gnu": "4.54.0", + "@rollup/rollup-linux-x64-gnu": "4.54.0", + "@rollup/rollup-linux-x64-musl": "4.54.0", + "@rollup/rollup-openharmony-arm64": "4.54.0", + "@rollup/rollup-win32-arm64-msvc": "4.54.0", + "@rollup/rollup-win32-ia32-msvc": "4.54.0", + "@rollup/rollup-win32-x64-gnu": "4.54.0", + "@rollup/rollup-win32-x64-msvc": "4.54.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-camel-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-camel-case/-/text-camel-case-1.2.9.tgz", + "integrity": "sha512-wKYs9SgRxYizJE1mneR7BbLNlGw2IYzJAS8XwkWIry0CTbO1gvvPkFsx5Z1/hr+VqUaBqx9q3yKd30HpZLdMsQ==", + "license": "MIT", + "dependencies": { + "text-pascal-case": "1.2.9" + } + }, + "node_modules/text-capital-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-capital-case/-/text-capital-case-1.2.9.tgz", + "integrity": "sha512-X5zV8U8pxtq2xS2t46lgAWqZdDbgWMKq03MQSNwY2CJdQCsdTNh144E2Q/q9wBxWzSBUXn+jRc9kF+Gs8/pGhA==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-case/-/text-case-1.2.9.tgz", + "integrity": "sha512-zZVdA8rMcjx9zhekdUuOPZShc25UTV7W8/ddKbgbPtfCEvIiToPtWiSd2lXLSuiGMovNhJ4+Tw49xll9o9ts+Q==", + "license": "MIT", + "dependencies": { + "text-camel-case": "1.2.9", + "text-capital-case": "1.2.9", + "text-constant-case": "1.2.9", + "text-dot-case": "1.2.9", + "text-header-case": "1.2.9", + "text-is-lower-case": "1.2.9", + "text-is-upper-case": "1.2.9", + "text-kebab-case": "1.2.9", + "text-lower-case": "1.2.9", + "text-lower-case-first": "1.2.9", + "text-no-case": "1.2.9", + "text-param-case": "1.2.9", + "text-pascal-case": "1.2.9", + "text-path-case": "1.2.9", + "text-sentence-case": "1.2.9", + "text-snake-case": "1.2.9", + "text-swap-case": "1.2.9", + "text-title-case": "1.2.9", + "text-upper-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-constant-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-constant-case/-/text-constant-case-1.2.9.tgz", + "integrity": "sha512-Vosm6nC7Gag+JFakJHwqS9AXRNgl07j5KZ7srU9cYuKRzYwrxzeJ4RpEogRBNHw7CfmOm0j5FGEznblWtu7pIw==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case": "1.2.9" + } + }, + "node_modules/text-dot-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-dot-case/-/text-dot-case-1.2.9.tgz", + "integrity": "sha512-N83hsnvGdSO9q9AfNSB9Cy1LFDNN2MCx53LcxtaPoDWPUTk47fv0JlvIY1tgY0wyzCiThF03kVj3jworvAOScA==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9" + } + }, + "node_modules/text-header-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-header-case/-/text-header-case-1.2.9.tgz", + "integrity": "sha512-TqryEKcYisQAfWLbtT3xPnZlMZ/mySO1uS+LUg+B0eNuqgETrSzVpXIUj5E6Zf/EyJHgpZf4VndbAXtOMJuT4w==", + "license": "MIT", + "dependencies": { + "text-capital-case": "1.2.9" + } + }, + "node_modules/text-is-lower-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-is-lower-case/-/text-is-lower-case-1.2.9.tgz", + "integrity": "sha512-cEurrWSnYVYqL8FSwl5cK4mdfqF7qNDCcKJgXI3NnfTesiB8umxAhdlQoErrRYI1xEvYr2WN0MI333EehUhQjg==", + "license": "MIT" + }, + "node_modules/text-is-upper-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-is-upper-case/-/text-is-upper-case-1.2.9.tgz", + "integrity": "sha512-HxsWr3VCsXXiLlhD0c+Ey+mS2lOTCiSJbkepjaXNHl2bp33KiscQaiG0qLwQmmpZQm4SJCg2s9FkndxS0RNDLQ==", + "license": "MIT" + }, + "node_modules/text-kebab-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-kebab-case/-/text-kebab-case-1.2.9.tgz", + "integrity": "sha512-nOUyNR5Ej2B9D/wyyXfwUEv26+pQuOb1pEX+ojE37mCIWo8QeOxw5y6nxuqDmG7NrEPzbO6265UMV+EICH13Cw==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9" + } + }, + "node_modules/text-lower-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-lower-case/-/text-lower-case-1.2.9.tgz", + "integrity": "sha512-53AOnDrhPpiAUQkgY1SHleKUXp/u7GsqRX13NcCREZscmtjLLJ099uxMRjkK7q2KwHkFYVPl9ytkQlTkTQLS0w==", + "license": "MIT" + }, + "node_modules/text-lower-case-first": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-lower-case-first/-/text-lower-case-first-1.2.9.tgz", + "integrity": "sha512-iiphHTV7PVH0MljrEQUA9iBE7jfDpXoi4RQju3WzZU3BRVbS6540cNZgxR19hWa0z6z/7cJTH0Ls9LPBaiUfKg==", + "license": "MIT" + }, + "node_modules/text-no-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-no-case/-/text-no-case-1.2.9.tgz", + "integrity": "sha512-IcCt328KaapimSrytP4ThfC8URmHZb2DgOqCL9BYvGjpxY2lDiqCkIQk9sClZtwcELs2gTnq83a7jNc573FTLA==", + "license": "MIT", + "dependencies": { + "text-lower-case": "1.2.9" + } + }, + "node_modules/text-param-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-param-case/-/text-param-case-1.2.9.tgz", + "integrity": "sha512-nR/Ju9amY3aQS1en2CUCgqN/ZiZIVdDyjlJ3xX5J92ChBevGuA4o9K10fh3JGMkbzK97Vcb+bWQJ4Q+Svz+GyQ==", + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.9" + } + }, + "node_modules/text-pascal-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-pascal-case/-/text-pascal-case-1.2.9.tgz", + "integrity": "sha512-o6ZxMGjWDTUW54pcghpXes+C2PqbYRMdU5mHrIhueb6z6nq1NueiIOeCUdrSjN/3wXfhCmnFjK7/d9aRGZNqSg==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9" + } + }, + "node_modules/text-path-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-path-case/-/text-path-case-1.2.9.tgz", + "integrity": "sha512-s8cJ6r5TkJp5ticXMgtxd7f12odEN4d1CfX5u4aoz6jcUtBR2lDqzIhVimkqWFMJ4UKPSrmilUha8Xc2BPi+ow==", + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.9" + } + }, + "node_modules/text-sentence-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-sentence-case/-/text-sentence-case-1.2.9.tgz", + "integrity": "sha512-/G/Yi5kZfUa1edFRV4O3lGZAkbDZTFvlwW8CYfH7szkEGe2k2MYEYbOyAkGRVQEGV6V6JiuUAaP3VS9c1tB6nQ==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-snake-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-snake-case/-/text-snake-case-1.2.9.tgz", + "integrity": "sha512-+ZrqK19ynF/TLQZ7ynqVrL2Dy04uu9syYZwsm8PhzUdsY3XrwPy6QiRqhIEFqhyWbShPcfyfmheer5UEQqFxlw==", + "license": "MIT", + "dependencies": { + "text-dot-case": "1.2.9" + } + }, + "node_modules/text-swap-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-swap-case/-/text-swap-case-1.2.9.tgz", + "integrity": "sha512-g5fp12ldktYKK9wdHRMvvtSCQrZYNv/D+ZGLumDsvAY4q9T5bCMO2IWMkIP1F5gVQrysdHH6Xv877P/pjUq1iw==", + "license": "MIT" + }, + "node_modules/text-title-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-title-case/-/text-title-case-1.2.9.tgz", + "integrity": "sha512-RAtC9cdmPp41ns5/HXZBsaQg71BsHT7uZpj2ojTtuFa8o2dNuRYYOrSmy5YdLRIAJQ6WK5hQVpV3jHuq7a+4Tw==", + "license": "MIT", + "dependencies": { + "text-no-case": "1.2.9", + "text-upper-case-first": "1.2.9" + } + }, + "node_modules/text-upper-case": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-upper-case/-/text-upper-case-1.2.9.tgz", + "integrity": "sha512-K/0DNT7a4z8eah2spARtoJllTZyrNTo6Uc0ujhN/96Ir9uJ/slpahfs13y46H9osL3daaLl3O7iXOkW4xtX6bg==", + "license": "MIT" + }, + "node_modules/text-upper-case-first": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/text-upper-case-first/-/text-upper-case-first-1.2.9.tgz", + "integrity": "sha512-wEDD1B6XqJmEV+xEnBJd+2sBCHZ+7fvA/8Rv/o8+dAsp05YWjYP/kjB8sPH6zqzW0s6jtehIg4IlcKjcYxk2CQ==", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tsdown": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/tsdown/-/tsdown-0.18.2.tgz", + "integrity": "sha512-2o6p/9WjcQrgKnz5/VppOstsqXdTER6G6gPe5yhuP57AueIr2y/NQFKdFPHuqMqZpxRLVjm7MP/dXWG7EJpehg==", + "license": "MIT", + "dependencies": { + "ansis": "^4.2.0", + "cac": "^6.7.14", + "defu": "^6.1.4", + "empathic": "^2.0.0", + "hookable": "^6.0.1", + "import-without-cache": "^0.2.5", + "obug": "^2.1.1", + "picomatch": "^4.0.3", + "rolldown": "1.0.0-beta.55", + "rolldown-plugin-dts": "^0.19.1", + "semver": "^7.7.3", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tree-kill": "^1.2.2", + "unconfig-core": "^7.4.2", + "unrun": "^0.2.20" + }, + "bin": { + "tsdown": "dist/run.mjs" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@arethetypeswrong/core": "^0.18.1", + "@vitejs/devtools": "*", + "publint": "^0.3.0", + "typescript": "^5.0.0", + "unplugin-lightningcss": "^0.4.0", + "unplugin-unused": "^0.5.0" + }, + "peerDependenciesMeta": { + "@arethetypeswrong/core": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "publint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "unplugin-lightningcss": { + "optional": true + }, + "unplugin-unused": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/tslog": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/tslog/-/tslog-4.10.2.tgz", + "integrity": "sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/fullstack-build/tslog?sponsor=1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unconfig-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.2.tgz", + "integrity": "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==", + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrun": { + "version": "0.2.20", + "resolved": "https://registry.npmjs.org/unrun/-/unrun-0.2.20.tgz", + "integrity": "sha512-YhobStTk93HYRN/4iBs3q3/sd7knvju1XrzwwrVVfRujyTG1K88hGONIxCoJN0PWBuO+BX7fFiHH0sVDfE3MWw==", + "license": "MIT", + "dependencies": { + "rolldown": "1.0.0-beta.55" + }, + "bin": { + "unrun": "dist/cli.mjs" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/Gugustinette" + }, + "peerDependencies": { + "synckit": "^0.11.11" + }, + "peerDependenciesMeta": { + "synckit": { + "optional": true + } + } + }, + "node_modules/vite": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", + "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.16.tgz", + "integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/expect": "4.0.16", + "@vitest/mocker": "4.0.16", + "@vitest/pretty-format": "4.0.16", + "@vitest/runner": "4.0.16", + "@vitest/snapshot": "4.0.16", + "@vitest/spy": "4.0.16", + "@vitest/utils": "4.0.16", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.16", + "@vitest/browser-preview": "4.0.16", + "@vitest/browser-webdriverio": "4.0.16", + "@vitest/ui": "4.0.16", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/packages/globe_runtime_ts/dart_source_generator/package.json b/packages/globe_runtime_ts/dart_source_generator/package.json new file mode 100644 index 0000000..49756e2 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/package.json @@ -0,0 +1,42 @@ +{ + "name": "@globe/dart_source_generator", + "version": "1.0.0", + "description": "Generate Dart source files from TypeScript declarations and JavaScript source for use with the Dart JS runtime interop", + "types": "dist/index.d.ts", + "main": "dist/index.js", + "sideEffects": false, + "scripts": { + "build": "npm run clean && tsc", + "watch": "npm run build -- --watch", + "clean": "rm -rf dist", + "test": "vitest", + "test:run": "vitest run", + "test:coverage": "vitest run --coverage.enabled --coverage.reporter=lcov --coverage.reporter=text" + }, + "bin": { + "globe-dart-source-generator": "./dist/bin/generate.js" + }, + "dependencies": { + "typescript": "^5.9.3", + "tsdown": "^0.18.2", + "glob": "^13.0.0", + "tslog": "^4.10.2", + "text-case": "^1.2.9" + }, + "devDependencies": { + "@types/node": "^25.0.3", + "@vitest/coverage-v8": "^4.0.16", + "vitest": "^4.0.16", + "@globe/runtime_types": "workspace:*" + }, + "keywords": [ + "dart", + "ffi", + "v8", + "interop", + "globe", + "runtime", + "code generation" + ], + "license": "MIT" +} diff --git a/packages/globe_runtime_ts/dart_source_generator/src/ast-parser.ts b/packages/globe_runtime_ts/dart_source_generator/src/ast-parser.ts new file mode 100644 index 0000000..c944259 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/src/ast-parser.ts @@ -0,0 +1,603 @@ +/** + * TypeScript AST parsing utilities for extracting function definitions + */ + +import ts from "typescript"; +import { mapTsTypeToDart } from "./type-mapper"; +import type { ArgType, FuncType, ParseResult } from "./types"; +import { camelCase } from "text-case"; + +/** + * Parses a TypeScript declaration file to extract init function arguments and worker functions + * @param dtsFilePath - Path to the .d.ts file + * @returns Parsed init arguments and functions + */ +export function parseDeclarationFile(dtsFilePath: string): ParseResult | null { + const program = ts.createProgram([dtsFilePath], {}); + const sourceFile = program.getSourceFile(dtsFilePath); + const checker = program.getTypeChecker(); + + if (!sourceFile) { + throw new Error(`Could not read source file: ${dtsFilePath}`); + } + + // Build a map of type aliases for direct resolution + const typeAliasMap = parseTypeAliasMap(sourceFile); + try { + // Get SDK types + const { initArgsType, funcsType } = getSdkTypes(sourceFile, typeAliasMap); + + // Parse SDK types + return parseSdkTypes({ + initArgsType, + typeAliasMap, + checker, + funcsType, + sourceFile, + }); + } catch (error) { + console.error(error); + return null; + } +} + +/** + * Parses a TypeScript declaration file to extract init function arguments and worker functions + * @param params - Object containing source file, type alias map, and checker + * @param params.sourceFile - Source file to parse + * @param params.typeAliasMap - Map of type aliases + * @param params.checker - TypeScript type checker + * @returns Parsed init arguments and functions + */ +export function parseInitArgsAndFunctions({ + sourceFile, + typeAliasMap, + checker, +}: { + sourceFile: ts.SourceFile; + typeAliasMap: Map; + checker: ts.TypeChecker; +}): ParseResult { + // Get SDK types + const { initArgsType, funcsType } = getSdkTypes(sourceFile, typeAliasMap); + + // Parse SDK types + return parseSdkTypes({ + initArgsType, + typeAliasMap, + checker, + funcsType, + sourceFile, + }); +} + +/** + * Extracts the type argument from DartReturn or DartStreamReturn + * @param returnType - The return type node + * @param checker - TypeScript type checker + * @param typeAliasMap - Map of type aliases + * @returns The extracted return type and whether it's a stream + */ +function extractDartReturnType( + returnType: ts.TypeNode | undefined, + checker: ts.TypeChecker, + typeAliasMap: Map +): { type: { dart: string; ffi: string }; isStream: boolean } { + if (!returnType) { + return { type: { dart: "void", ffi: "Void" }, isStream: false }; + } + + // Check if it's a type reference (e.g., DartReturn or DartStreamReturn) + if (ts.isTypeReferenceNode(returnType)) { + const typeName = returnType.typeName.getText(); + + // Handle namespaced types like _globe_runtime_types0.DartReturn + if (typeName.includes("DartReturn") && returnType.typeArguments?.length) { + const typeArg = returnType.typeArguments[0]; + return { + type: mapDartCollectionType(typeArg, checker, typeAliasMap), + isStream: false, + }; + } + + if ( + typeName.includes("DartStreamReturn") && + returnType.typeArguments?.length + ) { + const typeArg = returnType.typeArguments[0]; + return { + type: mapDartCollectionType(typeArg, checker, typeAliasMap), + isStream: true, + }; + } + } + + // Check for plain void return + if (returnType.kind === ts.SyntaxKind.VoidKeyword) { + return { type: { dart: "void", ffi: "Void" }, isStream: false }; + } + + // If we get here, it's likely an unwrapped type - map it directly + return { + type: mapDartCollectionType(returnType, checker, typeAliasMap), + isStream: false, + }; +} + +/** + * Maps Dart collection marker types (DartMap, DartList, DartSet) to their Dart equivalents + * @param typeNode - The type node to map + * @param checker - TypeScript type checker + * @param typeAliasMap - Map of type aliases + * @returns Mapped Dart type + */ +function mapDartCollectionType( + typeNode: ts.TypeNode, + checker: ts.TypeChecker, + typeAliasMap: Map +): { dart: string; ffi: string } { + // Resolve type aliases first + const resolvedType = resolveTypeAlias(typeAliasMap, typeNode); + + // Fall back to standard type mapping + return mapTsTypeToDart(resolvedType, checker, typeAliasMap); +} + +/** + * Extracts JSDoc comment text from a node + * @param node - TypeScript node + * @returns Cleaned documentation text or undefined + */ +function extractJsDocComment(node: ts.Node): string | undefined { + const jsDocComments = ts.getJSDocCommentsAndTags(node); + + if (jsDocComments.length === 0) return undefined; + + // Get the first JSDoc comment + const firstComment = jsDocComments[0]; + if (!ts.isJSDoc(firstComment)) return undefined; + + // Extract the comment text + const commentText = firstComment.comment; + + if (typeof commentText === "string") { + return cleanJsDocComment(commentText); + } + + // Handle structured JSDoc comments (array of JSDocText/JSDocLink nodes) + if (Array.isArray(commentText)) { + const text = commentText + .map((part) => { + if (typeof part === "string") return part; + if ("text" in part) return part.text; + return ""; + }) + .join(""); + return cleanJsDocComment(text); + } + + return undefined; +} + +/** + * Cleans JSDoc comment text by removing asterisks and extra whitespace + * while preserving paragraph breaks + * @param text - Raw JSDoc comment text + * @returns Cleaned text with preserved paragraphs + */ +function cleanJsDocComment(text: string): string { + const lines = text.split("\n").map((line) => line.trim()); + + // Group lines into paragraphs (separated by empty lines) + const paragraphs: string[] = []; + let currentParagraph: string[] = []; + + const addCurrentParagraph = () => { + if (currentParagraph.length > 0) { + paragraphs.push(currentParagraph.join(" ")); + currentParagraph = []; + } + }; + + for (const line of lines) { + if (line.length === 0) { + // Empty line - end current paragraph + addCurrentParagraph(); + } else { + currentParagraph.push(line); + } + } + + // Add the last paragraph if any + addCurrentParagraph(); + + // Join paragraphs with double newline + return paragraphs.join("\n\n").trim(); +} + +/** + * Extracts parameter documentation from JSDoc + * @param node - TypeScript node + * @returns Map of parameter name to documentation + */ +function extractParamDocs(node: ts.Node): Map { + const paramDocs = new Map(); + const jsDocTags = ts.getJSDocTags(node); + + for (const tag of jsDocTags) { + if (tag.tagName.text === "param" && ts.isJSDocParameterTag(tag)) { + const paramName = tag.name.getText(); + const comment = tag.comment; + + let text = ""; + if (typeof comment === "string") { + text = comment; + } else if (Array.isArray(comment)) { + text = comment + .map((part) => (typeof part === "string" ? part : part.text)) + .join(""); + } + + // Remove leading dash and whitespace that JSDoc often includes + text = text.replace(/^\s*-\s*/, ""); + + paramDocs.set(paramName, cleanJsDocComment(text)); + } + } + + return paramDocs; +} + +/** + * Extracts return documentation from JSDoc + * @param node - TypeScript node + * @returns Return documentation or undefined + */ +function extractReturnDoc(node: ts.Node): string | undefined { + const jsDocTags = ts.getJSDocTags(node); + + for (const tag of jsDocTags) { + if (tag.tagName.text === "returns" || tag.tagName.text === "return") { + const comment = tag.comment; + + if (typeof comment === "string") { + return cleanJsDocComment(comment); + } else if (Array.isArray(comment)) { + const text = comment + .map((part) => (typeof part === "string" ? part : part.text)) + .join(""); + return cleanJsDocComment(text); + } + } + } + + return undefined; +} + +/** + * Parses SDK types with documentation + */ +function parseSdkTypes({ + initArgsType, + typeAliasMap, + checker, + funcsType, + sourceFile, +}: { + initArgsType: ts.TupleTypeNode | ts.NodeArray; + typeAliasMap: Map; + checker: ts.TypeChecker; + funcsType: ts.TypeNode; + sourceFile?: ts.SourceFile; +}) { + // Extract init function documentation if sourceFile is provided + let initDescription: string | undefined; + let initParamDocs = new Map(); + + if (sourceFile) { + const initFunction = findInitFunction(sourceFile); + if (initFunction) { + initDescription = extractJsDocComment(initFunction); + initParamDocs = extractParamDocs(initFunction); + } + } + + const elements = ts.isTupleTypeNode(initArgsType as ts.Node) + ? (initArgsType as ts.TupleTypeNode).elements + : (initArgsType as ts.NodeArray); + + const initArgs = (elements as readonly any[]).map((el): ArgType => { + let type: ts.TypeNode; + let name = "arg"; + + if (ts.isParameter(el)) { + name = el.name.getText(); + type = el.type || (checker.getTypeAtLocation(el) as any); + } else if (ts.isNamedTupleMember(el)) { + name = el.name.getText(); + type = el.type; + } else { + type = el as ts.TypeNode; + } + + const resolvedType = resolveTypeAlias(typeAliasMap, type); + const camelName = camelCase(name); + + return { + name: camelName, + type: mapTsTypeToDart(resolvedType, checker, typeAliasMap), + description: initParamDocs.get(name) || initParamDocs.get(camelName), + }; + }); + + // Check if Fns is a type literal node + if (!ts.isTypeLiteralNode(funcsType)) { + throw new Error("Fns must be a type literal node"); + } + + // Extract Fns with documentation + const functions: FuncType[] = []; + for (const member of funcsType.members) { + if ( + ts.isPropertySignature(member) && + member.type && + ts.isFunctionTypeNode(member.type) + ) { + const funcName = member.name.getText(); + const sig = member.type; + + // Extract documentation + const description = extractJsDocComment(member); + const paramDocs = extractParamDocs(member); + const returnDoc = extractReturnDoc(member); + + // Extract return type from DartReturn or DartStreamReturn + const { type: retType, isStream } = extractDartReturnType( + sig.type, + checker, + typeAliasMap + ); + + // Params (skip state (0) and callbackId (last)) + const params = sig.parameters.filter( + (_, i) => i !== 0 && i !== sig.parameters.length - 1 + ); + + // Format args with documentation + const args = params.map((p) => { + const paramName = p.name.getText(); + return { + name: camelCase(paramName), + type: mapTsTypeToDart(p.type, checker, typeAliasMap), + description: paramDocs.get(paramName), + }; + }); + + functions.push({ + name: funcName, + dartName: camelCase(funcName), + returnType: retType, + isStream, + args, + description, + returnDescription: returnDoc, + }); + } + } + + return { initArgs, functions, initDescription }; +} + +/** + * Finds the init function in the source file + * @param sourceFile - Source file to search + * @returns Init function node or undefined + */ +function findInitFunction(sourceFile: ts.SourceFile): ts.Node | undefined { + // First look for the _default variable declaration in the .d.ts + const variableStatement = sourceFile.statements.find((stmt) => + ts.isVariableStatement(stmt) + ) as ts.VariableStatement; + + if (variableStatement) { + const decl = variableStatement.declarationList.declarations[0]; + if (decl.name.getText() === "_default" && decl.type) { + // Check if it's an intersection type (typeof def & Sdk) + let type = decl.type; + + const typesToSearch = ts.isIntersectionTypeNode(type) + ? type.types + : [type]; + + for (const t of typesToSearch) { + if (ts.isTypeLiteralNode(t)) { + const initProp = t.members.find((m) => { + return ( + (ts.isPropertySignature(m) || ts.isMethodSignature(m)) && + m.name.getText() === "init" + ); + }); + if (initProp) { + return initProp; + } + } + } + } + } + + // Fallback to searching for object literal (useful for tests on raw .ts files) + let initFunction: ts.Node | undefined; + + function visit(node: ts.Node) { + // Look for object literal with 'init' property + if (ts.isObjectLiteralExpression(node)) { + for (const prop of node.properties) { + if ( + ts.isPropertyAssignment(prop) || + ts.isMethodDeclaration(prop) || + ts.isShorthandPropertyAssignment(prop) + ) { + const name = prop.name?.getText(); + if (name === "init") { + // Found the init property + if (ts.isPropertyAssignment(prop)) { + initFunction = prop.initializer; + } else if (ts.isMethodDeclaration(prop)) { + initFunction = prop; + } + return; + } + } + } + } + + ts.forEachChild(node, visit); + } + + visit(sourceFile); + return initFunction; +} + +/** + * Gets the SDK declaration from the source file + * @param sourceFile - Source file to parse + * @returns SDK declaration + */ +export function getSdkTypes( + sourceFile: ts.SourceFile, + typeAliasMap: Map = new Map() +): { + initArgsType: ts.TupleTypeNode | ts.NodeArray; + funcsType: ts.TypeNode; +} { + // Get the variable statement in the source file, + // only one expected exported as _default + const variableStatement = sourceFile.statements.find((stmt) => + ts.isVariableStatement(stmt) + ) as ts.VariableStatement; + + if (!variableStatement) { + throw new Error("Could not find SDK definition in declaration file"); + } + + const decl = variableStatement.declarationList.declarations[0]; + // Check if it's the _default constraint + if (decl.name.getText() !== "_default") { + throw new Error("Could not find default export in declaration file"); + } + + // Check if it has a type + if (!decl.type) { + throw new Error("Could not find Sdk type in declaration file"); + } + + // Handle intersection type: typeof def & Sdk + let sdkType: ts.TypeReferenceNode | undefined; + let funcsType: ts.TypeNode | undefined; + + const types = ts.isIntersectionTypeNode(decl.type) + ? decl.type.types + : [decl.type]; + + for (const t of types) { + if (ts.isTypeReferenceNode(t) && t.typeName.getText().includes("Sdk")) { + sdkType = t; + } else if (ts.isTypeLiteralNode(t)) { + // Potentially the 'functions' part if it was inlined + const funcsProp = t.members.find( + (m) => ts.isPropertySignature(m) && m.name.getText() === "functions" + ) as ts.PropertySignature; + if (funcsProp?.type) { + funcsType = funcsProp.type; + } + } + } + + if (!sdkType) { + throw new Error("Could not find Sdk type reference in declaration file"); + } + + // Check if it has 2 type arguments (i.e. Sdk) + if ((sdkType.typeArguments?.length ?? 0) < 2) { + throw new Error( + "Sdk type must have at least 2 type arguments. expected Sdk" + ); + } + + // Get type arguments + const typeArgs = sdkType.typeArguments!; + let initFnType = typeArgs[0]; + funcsType = funcsType || typeArgs[1]; + + // Resolve type aliases, if present + initFnType = resolveTypeAlias(typeAliasMap, initFnType); + funcsType = resolveTypeAlias(typeAliasMap, funcsType); + + // InitFn can be a FunctionTypeNode or a TypeReference (if it's a named function) + if (ts.isFunctionTypeNode(initFnType)) { + return { initArgsType: initFnType.parameters, funcsType }; + } + + // Check if InitFn is a tuple type (old way, for compatibility if needed, + // though we are upgrading everything) + if (ts.isTupleTypeNode(initFnType)) { + return { initArgsType: initFnType, funcsType }; + } + + throw new Error( + `InitFn must be a function type. found: ${initFnType.getText()}` + ); +} + +/** + * Determine if a file has an SDK declaration + * @param sourceFile - Source file to parse + * @returns true if the file has an SDK declaration + */ +export function hasSdkDeclaration(sourceFile: ts.SourceFile) { + try { + // Build a map of type aliases for direct resolution + const typeAliasMap = parseTypeAliasMap(sourceFile); + getSdkTypes(sourceFile, typeAliasMap); + return true; + } catch (e) { + return false; + } +} + +/** + * Parses a TypeScript declaration file to extract type aliases + * @param sourceFile - Source file to parse + * @returns Map of type aliases + */ +export function parseTypeAliasMap( + sourceFile: ts.SourceFile +): Map { + const typeAliasMap = new Map(); + ts.forEachChild(sourceFile, (node) => { + if (ts.isTypeAliasDeclaration(node)) { + typeAliasMap.set(node.name.text, node.type); + } + }); + return typeAliasMap; +} + +/** + * Resolves type aliases in a TypeScript AST + * @param typeAliasMap - Map of type aliases + * @param typeNode - Type node to resolve + * @returns Resolved type node + */ +export function resolveTypeAlias( + typeAliasMap: Map, + typeNode: ts.TypeNode +): ts.TypeNode { + if (ts.isTypeReferenceNode(typeNode)) { + const typeName = typeNode.typeName.getText(); + const resolvedType = typeAliasMap.get(typeName); + if (resolvedType) { + return resolveTypeAlias(typeAliasMap, resolvedType); + } + } + return typeNode; +} diff --git a/packages/globe_runtime_ts/dart_source_generator/src/dart-codegen.ts b/packages/globe_runtime_ts/dart_source_generator/src/dart-codegen.ts new file mode 100644 index 0000000..aa0c359 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/src/dart-codegen.ts @@ -0,0 +1,400 @@ +/** + * Dart code generation utilities + */ + +import type { ArgType, FuncType } from "./types"; + +/** + * Formats documentation for Dart + * @param text - Documentation text (may contain \n\n for paragraph breaks) + * @param indent - Indentation level (number of spaces) + * @returns Formatted Dart doc comment + */ +function formatDartDoc(text: string | undefined, indent: number = 2): string { + if (!text) return ""; + + const spaces = " ".repeat(indent); + + // Split by double newlines (paragraphs) + const paragraphs = text.split("\n\n").filter((p) => p.trim().length > 0); + + if (paragraphs.length === 0) return ""; + + // Format each paragraph + const formattedParagraphs = paragraphs.map((paragraph) => { + // Split long lines at word boundaries + const words = paragraph.split(/\s+/); + const lines: string[] = []; + let currentLine = ""; + + // Maximum length of the line + const maxLength = 80; + + for (const word of words) { + if (currentLine.length + word.length + 1 > maxLength) { + if (currentLine) { + lines.push(currentLine); + currentLine = word; + } else { + // Word itself is longer than maxLength chars + lines.push(word); + } + } else { + currentLine = currentLine ? `${currentLine} ${word}` : word; + } + } + + if (currentLine) { + lines.push(currentLine); + } + + return lines.map((line) => `${spaces}/// ${line}`).join("\n"); + }); + + // Join paragraphs with a single comment line separator + return formattedParagraphs.join(`\n${spaces}///\n`) + "\n"; +} + +/** + * Formats parameter documentation for Dart + * @param args - Function arguments + * @param indent - Indentation level + * @returns Formatted parameter docs + */ +function formatParamDocs(args: ArgType[], indent: number = 2): string { + const spaces = " ".repeat(indent); + const paramDocs = args + .filter((arg) => arg.description) + .map((arg) => `${spaces}/// * [${arg.name}]: ${arg.description}`) + .join("\n"); + + if (paramDocs) { + return `${spaces}///\n${spaces}/// **Parameters:**\n${paramDocs}\n`; + } + + return ""; +} + +/** + * Formats return documentation for Dart + * @param returnDoc - Return documentation + * @param returnType - Dart return type + * @param indent - Indentation level + * @returns Formatted return docs + */ +function formatReturnDoc( + returnDoc: string | undefined, + returnType: string, + indent: number = 2 +): string { + const spaces = " ".repeat(indent); + + const returns = returnDoc ? returnDoc : returnType; + + if (returns && returns !== "void") { + return `${spaces}///\n${spaces}/// **Returns:** \`${returns}\`\n`; + } + + return ""; +} + +/** + * Generates a complete Dart class from parsed function definitions + * @param params - Object containing class name, version, source, init args, and functions + * @param params.className - Name of the Dart class to generate + * @param params.version - Version string for the package + * @param params.jsSource - JavaScript source code to embed + * @param params.initArgs - Initialization function arguments + * @param params.functions - Worker functions + * @param params.initDescription - Optional init function documentation + * @returns Generated Dart source code + */ +export function generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + initDescription, +}: { + className: string; + version: string; + jsSource: string; + initArgs: ArgType[]; + functions: FuncType[]; + initDescription?: string; +}): string { + const createParams = initArgs + .map((a) => `${a.type.dart}? ${a.name}`) + .join(", "); + const registerArgs = initArgs + .map((a) => `${a.name}?.toFFIType`) + .join(",\n "); + const createArgs = createParams.length > 0 ? `{${createParams}}` : ""; + + // Generate init documentation + let initDocs = ""; + + if (initDescription) { + initDocs += formatDartDoc(initDescription); + } else { + initDocs += formatDartDoc(`Create instance of ${className} class`); + } + + // Add parameter documentation if available + if (initArgs.length > 0 && initArgs.some((arg) => arg.description)) { + initDocs += formatParamDocs(initArgs); + } + + const dartCode = ` +// GENERATED FILE — DO NOT MODIFY BY HAND +// This file was generated from @globe/dart_source_generator +// ignore_for_file: unused_import + +import 'dart:async'; +import 'dart:convert'; +import 'package:globe_runtime/globe_runtime.dart'; + +/// Package version +const packageVersion = '${version}'; + +/// Package source code +const packageSource = r''' +${jsSource} +'''; + +/// {@template ${className}} +/// ${className} class +/// {@endtemplate} +class ${className} { + /// {@macro ${className}} + ${className}._(this._module); + + /// Module instance + final Module _module; + +${initDocs} static Future<${className}> create(${createArgs}) async { + const module = InlinedModule( + name: '${className}', + sourceCode: packageSource, + ); + + await module.register(args: [ + ${registerArgs} + ]); + return ${className}._(module); + } + + /// Disposes of the runtime instance + void dispose() { + GlobeRuntime.instance.dispose(); + } + + ${generateWorkerFunctions(functions)} +} +`; + + return dartCode; +} + +/** + * Generates all worker function methods for the Dart class + * @param functions - List of functions to generate + * @returns Generated function code + */ +function generateWorkerFunctions(functions: FuncType[]): string { + return functions.map((f) => generateSingleFunction(f)).join("\n"); +} + +/** + * Generates a single worker function method + * @param func - Function definition + * @returns Generated function code + */ +function generateSingleFunction(func: FuncType): string { + return func.isStream + ? generateStreamFunction(func) + : generateSingleValueFunction(func); +} + +/** + * Generates function documentation + * @param func - Function definition + * @returns Formatted documentation + */ +function generateFunctionDocs(func: FuncType): string { + let docs = ""; + + // Main description + if (func.description) { + docs += formatDartDoc(func.description); + } else { + docs += formatDartDoc(`${func.dartName} function`); + } + + // Parameter documentation + if (func.args.length > 0) { + docs += formatParamDocs(func.args); + } + + // Return documentation + const returnTypeStr = func.isStream + ? `Stream<${func.returnType.dart}>` + : `Future<${func.returnType.dart}>`; + docs += formatReturnDoc(func.returnDescription, returnTypeStr); + + return docs; +} + +/** + * Generates a single-value worker function method + * @param func - Function definition + * @returns Generated function code + */ +function generateSingleValueFunction(func: FuncType): string { + const params = func.args + .map((a: ArgType) => `${a.type.dart} ${a.name}`) + .join(", "); + + const callArgs = func.args + .map((a: ArgType) => `${a.name}.toFFIType`) + .join(", "); + + const returnTypeHandling = + func.returnType.dart !== "void" + ? generateReturnTypeHandling(func.returnType.dart) + : generateVoidHandling(); + + const docs = generateFunctionDocs(func); + + return ` +${docs} Future<${func.returnType.dart}> ${func.dartName}(${params}) async { + final completer = Completer<${func.returnType.dart}>(); + + _module.callFunction( + '${func.name}', + args: [${callArgs}], + onData: (data) { + if (data.hasError()) { + completer.completeError(data.error); + } else { + ${returnTypeHandling} + } + return true; + }, + ); + + return completer.future; + } + `; +} + +/** + * Generates a streaming worker function method + * @param func - Function definition + * @returns Generated function code + */ +function generateStreamFunction(func: FuncType): string { + const params = func.args + .map((a: ArgType) => `${a.type.dart} ${a.name}`) + .join(", "); + + const callArgs = func.args + .map((a: ArgType) => `${a.name}.toFFIType`) + .join(", "); + + const streamValueHandling = generateStreamValueHandling(func.returnType.dart); + + const docs = generateFunctionDocs(func); + + return ` +${docs} Stream<${func.returnType.dart}> ${func.dartName}(${params}) { + final controller = StreamController<${func.returnType.dart}>(); + + _module.callFunction( + '${func.name}', + args: [${callArgs}], + onData: (data) { + if (data.hasError()) { + controller.addError(data.error); + return true; + } + + ${streamValueHandling} + + return false; // Keep listening for more data + }, + ); + + return controller.stream; + } + `; +} + +/** + * Generates code for handling non-void return types + * @param dartType - Dart type name + * @returns Generated handling code + */ +function generateReturnTypeHandling(dartType: string): string { + const { dataMethodCall, resultType } = getValueHandling(dartType); + return ` + final value = data.data${dataMethodCall}; + completer.complete(${resultType}); + `; +} + +/** + * Generates code for handling stream values + * @param dartType - Dart type name + * @returns Generated handling code + */ +export function generateStreamValueHandling(dartType: string): string { + const { dataMethodCall, resultType } = getValueHandling(dartType); + + return ` + if (data.hasData()) { + final value = data.data${dataMethodCall}; + controller.add(${resultType}); + } + + if (data.done) { + controller.close(); + return true; + } + `; +} + +/** + * Get dataMethodCall and resultType based on Dart type + * @param dartType - Dart type name + * @returns Object containing dataMethodCall and resultType + */ +function getValueHandling(dartType: string) { + const isString = dartType === "String"; + const isList = dartType === "List"; + const isSet = dartType === "Set"; + const returnData = isString || isList; + const dataMethodCall = returnData ? "" : ".unpack()"; + + switch (true) { + case isString: + return { dataMethodCall, resultType: "utf8.decode(value)" }; + case isList: + return { dataMethodCall, resultType: "value" }; + case isSet: + return { dataMethodCall, resultType: "Set.from(value)" }; + default: + return { dataMethodCall, resultType: `value as ${dartType}` }; + } +} + +/** + * Generates code for handling void return types + * @returns Generated handling code + */ +function generateVoidHandling(): string { + return ` + completer.complete(); + `; +} diff --git a/packages/globe_runtime_ts/dart_source_generator/src/index.ts b/packages/globe_runtime_ts/dart_source_generator/src/index.ts new file mode 100644 index 0000000..d23b2e8 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/src/index.ts @@ -0,0 +1,69 @@ +/** + * Main entry point for generating Dart source files from TypeScript definitions + */ + +import { execSync } from "child_process"; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"; +import { dirname } from "path"; +import { pascalCase } from "text-case"; +import { parseDeclarationFile } from "./ast-parser"; +import { generateDartClass } from "./dart-codegen"; +import type { GenerateDartSourceOptions } from "./types"; + +/** + * Generates a Dart source file from TypeScript declaration and JavaScript source + * @param options - Configuration options for generation + * @returns true if generation was successful, false otherwise + */ +export function generateDartSourceFile( + options: GenerateDartSourceOptions +): boolean { + const { jsSourcePath, dtsFilePath, outputPath, fileName, version } = options; + + // Read the JavaScript source + const jsSource = readFileSync(jsSourcePath, "utf8"); + + // Parse the TypeScript declaration file + const result = parseDeclarationFile(dtsFilePath); + + if (!result) { + console.error( + "Could not parse SDK definition from declaration file", + dtsFilePath + ); + return false; + } + + const { initArgs, functions, initDescription } = result; + + // Generate the class name from package name + const className = pascalCase(fileName); + + // Generate Dart code + const dartCode = generateDartClass({ + className, + version: version ?? "0.0.0", + jsSource, + initArgs, + functions, + initDescription, + }); + + // Ensure output directory exists + const outputDir = dirname(outputPath); + if (!existsSync(outputDir)) { + mkdirSync(outputDir, { recursive: true }); + } + + // Write the Dart file + writeFileSync(outputPath, dartCode); + + // Run dart format on the Dart file + execSync(`dart format ${outputPath}`); + + // Generation was successful + return true; +} + +// Re-export types for consumers +export type { GenerateDartSourceOptions } from "./types"; diff --git a/packages/globe_runtime_ts/dart_source_generator/src/type-mapper.ts b/packages/globe_runtime_ts/dart_source_generator/src/type-mapper.ts new file mode 100644 index 0000000..dfdfb29 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/src/type-mapper.ts @@ -0,0 +1,264 @@ +/** + * Type mapping utilities for converting TypeScript types to Dart types + */ + +import ts from "typescript"; +import type { DartType } from "./types.js"; + +/** + * Recursively gets the entity name from a TypeScript entity name + * @param name - The TypeScript entity name to get the name from + * @returns The entity name as a string + */ +function getEntityName(name: ts.EntityName): string { + if (ts.isIdentifier(name)) { + return name.text; + } + return `${getEntityName(name.left)}.${name.right.text}`; +} + +/** + * Maps a TypeScript type node to a Dart type representation + * @param typeNode - The TypeScript type node to map + * @param checker - Optional TypeScript type checker for resolving type aliases + * @param typeAliasMap - Optional map of type alias names to their resolved types + * @returns The mapped Dart type + */ +export function mapTsTypeToDart( + typeNode: ts.TypeNode | undefined, + checker?: ts.TypeChecker, + typeAliasMap?: Map +): DartType { + if (!typeNode) return { dart: "dynamic", ffi: "FFIJsonPayload" }; + + // Handle array types (string[], number[], etc.) + if (ts.isArrayTypeNode(typeNode)) { + const elementType = mapTsTypeToDart( + typeNode.elementType, + checker, + typeAliasMap + ); + return { + dart: `List<${elementType.dart}>`, + ffi: "FFIJsonPayload", + }; + } + + // First, try to resolve type aliases using the map + if (typeAliasMap && ts.isTypeReferenceNode(typeNode)) { + const typeName = getEntityName(typeNode.typeName); + + if (typeName) { + // Handle Dart collection marker types + if (typeName.includes("DartMap")) { + return { dart: "Map", ffi: "FFIJsonPayload" }; + } + if (typeName.includes("DartList")) { + return { dart: "List", ffi: "FFIJsonPayload" }; + } + if (typeName.includes("DartSet")) { + return { dart: "Set", ffi: "FFIJsonPayload" }; + } + + // Handle Array generic syntax + if (typeName === "Array" && typeNode.typeArguments?.length) { + const elementType = mapTsTypeToDart( + typeNode.typeArguments[0], + checker, + typeAliasMap + ); + return { + dart: `List<${elementType.dart}>`, + ffi: "FFIJsonPayload", + }; + } + + const resolvedType = typeAliasMap.get(typeName); + if (resolvedType) { + return mapTsTypeToDart(resolvedType, checker, typeAliasMap); + } + } + } + + // Resolve type aliases and references using the type checker + if (checker && ts.isTypeReferenceNode(typeNode)) { + const type = checker.getTypeAtLocation(typeNode); + + // Check if it's an array type via the type checker + const symbol = type.getSymbol(); + if (symbol?.getName() === "Array") { + const typeArgs = (type as ts.TypeReference).typeArguments; + if (typeArgs && typeArgs.length > 0) { + const elementTypeNode = checker.typeToTypeNode( + typeArgs[0], + undefined, + ts.NodeBuilderFlags.InTypeAlias + ); + if (elementTypeNode) { + const elementType = mapTsTypeToDart( + elementTypeNode, + checker, + typeAliasMap + ); + return { + dart: `List<${elementType.dart}>`, + ffi: "FFIJsonPayload", + }; + } + } + } + + // Handle union types (e.g., Language | undefined) + if (type.isUnion()) { + // Filter out undefined/null/void types + const nonNullTypes = type.types.filter( + (t) => + !(t.flags & ts.TypeFlags.Undefined) && + !(t.flags & ts.TypeFlags.Null) && + !(t.flags & ts.TypeFlags.Void) + ); + + // If we have exactly one non-null type, resolve it recursively + if (nonNullTypes.length === 1) { + const singleType = nonNullTypes[0]; + + // Check if it's a string literal union + if ( + singleType.isUnion() && + singleType.types.every((t: any) => t.isStringLiteral()) + ) { + return { dart: "String", ffi: "FFIString" }; + } + + // Check for primitive flags + if ( + singleType.flags & ts.TypeFlags.String || + singleType.flags & ts.TypeFlags.StringLiteral + ) { + return { dart: "String", ffi: "FFIString" }; + } + if ( + singleType.flags & ts.TypeFlags.Number || + singleType.flags & ts.TypeFlags.NumberLiteral + ) { + return { dart: "num", ffi: "FFINumber" }; + } + if ( + singleType.flags & + (ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral) + ) { + return { dart: "bool", ffi: "FFIBool" }; + } + } + + // Check if all non-null types are string literals + if (nonNullTypes.every((t: any) => t.isStringLiteral())) { + return { dart: "String", ffi: "FFIString" }; + } + + // Check if all non-null types are boolean-ish (true/false/boolean) + if ( + nonNullTypes.every( + (t) => + !!(t.flags & (ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral)) + ) + ) { + return { dart: "bool", ffi: "FFIBool" }; + } + } + + // If it's a primitive type alias, get the underlying type + if ( + type.flags & ts.TypeFlags.String || + type.flags & ts.TypeFlags.StringLiteral + ) { + return { dart: "String", ffi: "FFIString" }; + } + if ( + type.flags & ts.TypeFlags.Number || + type.flags & ts.TypeFlags.NumberLiteral + ) { + return { dart: "num", ffi: "FFINumber" }; + } + if (type.flags & (ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral)) { + return { dart: "bool", ffi: "FFIBool" }; + } + } + + // Handle Uint8Array + if (ts.isTypeReferenceNode(typeNode)) { + if ( + ts.isIdentifier(typeNode.typeName) && + typeNode.typeName.text === "Uint8Array" + ) { + return { dart: "List", ffi: "FFIBytes" }; + } + } + + switch (typeNode.kind) { + case ts.SyntaxKind.StringKeyword: + case ts.SyntaxKind.StringLiteral: + return { dart: "String", ffi: "FFIString" }; + case ts.SyntaxKind.LiteralType: + const literal = (typeNode as ts.LiteralTypeNode).literal; + if (literal.kind === ts.SyntaxKind.StringLiteral) { + return { dart: "String", ffi: "FFIString" }; + } + if (literal.kind === ts.SyntaxKind.NumericLiteral) { + return { dart: "num", ffi: "FFINumber" }; + } + if ( + literal.kind === ts.SyntaxKind.TrueKeyword || + literal.kind === ts.SyntaxKind.FalseKeyword + ) { + return { dart: "bool", ffi: "FFIBool" }; + } + return { dart: "dynamic", ffi: "FFIJsonPayload" }; + case ts.SyntaxKind.NumberKeyword: + return { dart: "num", ffi: "FFINumber" }; + case ts.SyntaxKind.BooleanKeyword: + case ts.SyntaxKind.TrueKeyword: + case ts.SyntaxKind.FalseKeyword: + return { dart: "bool", ffi: "FFIBool" }; + case ts.SyntaxKind.VoidKeyword: + return { dart: "void", ffi: "Void" }; + case ts.SyntaxKind.UnionType: + const union = typeNode as ts.UnionTypeNode; + const types = union.types.filter( + (t) => + t.kind !== ts.SyntaxKind.UndefinedKeyword && + t.kind !== ts.SyntaxKind.NullKeyword && + t.kind !== ts.SyntaxKind.VoidKeyword && + !( + ts.isLiteralTypeNode(t) && + t.literal.kind === ts.SyntaxKind.NullKeyword + ) + ); + + // If only one type remains after filtering, recursively resolve and map it + if (types.length === 1) { + // If it's a type reference, it might need resolution by the type alias map or checker + if (ts.isTypeReferenceNode(types[0])) { + // Try to recursively resolve by mapTsTypeToDart which will hit the TypeReference case + return mapTsTypeToDart(types[0], checker, typeAliasMap); + } + return mapTsTypeToDart(types[0], checker, typeAliasMap); + } + + if ( + types.every( + (t) => + ts.isLiteralTypeNode(t) && + t.literal.kind === ts.SyntaxKind.StringLiteral + ) + ) { + return { dart: "String", ffi: "FFIString" }; + } + + // Fallback to dynamic Dart Type + return { dart: "dynamic", ffi: "FFIJsonPayload" }; + + default: + return { dart: "dynamic", ffi: "FFIJsonPayload" }; + } +} diff --git a/packages/globe_runtime_ts/dart_source_generator/src/types.ts b/packages/globe_runtime_ts/dart_source_generator/src/types.ts new file mode 100644 index 0000000..85673de --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/src/types.ts @@ -0,0 +1,73 @@ +/** + * Type definitions for Dart code generation + */ + +/** + * Represents a Dart type mapping with both Dart and FFI type representations + */ +export interface DartType { + /** Dart type name (e.g., "String", "num", "bool") */ + dart: string; + /** FFI type name (e.g., "FFIString", "FFINumber", "FFIBool") */ + ffi: string; +} + +/** + * Represents a function argument with name and type information + */ +export interface ArgType { + /** Argument name in camelCase */ + name: string; + /** Dart type mapping */ + type: DartType; + /** Optional parameter documentation */ + description?: string; +} + +/** + * Represents a worker function definition + */ +export interface FuncType { + /** Original function name from TypeScript */ + name: string; + /** Dart-friendly camelCase function name */ + dartName: string; + /** Return type mapping */ + returnType: DartType; + /** Function arguments */ + args: ArgType[]; + /** Whether the function returns a stream */ + isStream?: boolean; + /** Optional function documentation */ + description?: string; + /** Optional return value documentation */ + returnDescription?: string; +} + +/** + * Result of parsing a TypeScript declaration file + */ +export interface ParseResult { + /** Initialization function arguments */ + initArgs: ArgType[]; + /** Worker functions */ + functions: FuncType[]; + /** Optional init function documentation */ + initDescription?: string; +} + +/** + * Options for generating Dart source code + */ +export interface GenerateDartSourceOptions { + /** Path to the JavaScript source file */ + jsSourcePath: string; + /** Path to the TypeScript declaration file (.d.ts) */ + dtsFilePath: string; + /** Path where the generated Dart file should be written */ + outputPath: string; + /** Package name (e.g., "pretty_node") */ + fileName: string; + /** Package version */ + version?: string; +} diff --git a/packages/globe_runtime_ts/dart_source_generator/test/bin/generate.test.ts b/packages/globe_runtime_ts/dart_source_generator/test/bin/generate.test.ts new file mode 100644 index 0000000..d0b7a97 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/test/bin/generate.test.ts @@ -0,0 +1,188 @@ +import { exec } from "child_process"; +import { constants, existsSync } from "fs"; +import { access, mkdir, rm, writeFile } from "fs/promises"; +import { join, resolve } from "path"; +import { promisify } from "util"; +import { + afterAll, + afterEach, + beforeAll, + beforeEach, + describe, + expect, + it, +} from "vitest"; + +const execAsync = promisify(exec); + +const TEST_DIR = resolve(__dirname, "generate-test-files"); +const OUTPUT_DIR = resolve(__dirname, "generate-test-output"); +const BIN_PATH = resolve(__dirname, "../../dist/bin/generate.js"); + +// Timeout for tests (30 seconds) +const timeout = 30000; + +describe("Generate Dart Source Command", () => { + // Create a dummy valid input file + const validFileContent = ` +import { defineSdk, returnString, returnNumber } from "@globe/runtime_types"; + +type ModuleState = { + apiKey: string; + timeout: number; +}; + +export default defineSdk({ + /** + * Initialize the SDK with authentication credentials + * + * This sets up the SDK with your API key and configures the timeout + * for all network requests. + * + * @param apiKey - Your API key for authentication + * @param timeout - Request timeout in milliseconds + */ + init(apiKey: string, timeout: number = 5000): ModuleState { + return { apiKey, timeout }; + }, + functions: { + /** + * Fetches user data from the API + * + * This function retrieves user information based on the provided user ID. + * It handles authentication automatically using the configured API key. + * + * @param userId - The unique identifier for the user + * @returns A JSON string containing the user's profile information + */ + getUserData: returnString( + (state: ModuleState, userId: string, callbackId: number) => { + // implementation + } + ), + + /** + * Calculates the sum of two numbers + * @param a - First number + * @param b - Second number + * @returns The sum of a and b + */ + calculateSum: returnNumber( + (state: ModuleState, a: number, b: number, callbackId: number) => { + // implementation + } + ), + }, +}); +`; + const fileName = "my-sdk.ts"; + const outputFileName = "my_sdk_source.dart"; + let filePath: string; + let testDir: string; + let outputDir: string; + + beforeAll(async () => { + if (!existsSync(BIN_PATH)) { + // Compile the project first to ensure dist/bin/generate.js exists + await execAsync("npm run build"); + } + }); + + beforeEach(async () => { + testDir = join(TEST_DIR, Date.now().toString()); + outputDir = join(OUTPUT_DIR, Date.now().toString()); + + await mkdir(testDir, { recursive: true }); + await mkdir(outputDir, { recursive: true }); + + filePath = join(testDir, fileName); + await writeFile(filePath, validFileContent); + }); + + afterEach(async () => { + await rm(testDir, { recursive: true, force: true }); + await rm(outputDir, { recursive: true, force: true }); + }); + + afterAll(async () => { + await rm(TEST_DIR, { recursive: true, force: true }); + await rm(OUTPUT_DIR, { recursive: true, force: true }); + }); + + it( + "should generate dart source for valid input file via CLI", + async () => { + // We run the built JS file using node + const cmd = `node ${BIN_PATH} --files ${filePath} --output ${outputDir} --verbose`; + + try { + const output = await execAsync(cmd); + console.log(output.stdout); + console.error(output.stderr); + } catch (e: any) { + console.error("Bundler failed:", e.stdout, e.stderr); + throw e; + } + + // Check if output exists + const dartFile = join(outputDir, outputFileName); + + // We expect the file to exist. + // Use access to check existence + await expect(access(dartFile, constants.F_OK)).resolves.toBeUndefined(); + }, + timeout + ); + + it( + "should generate dart source for valid input folder via CLI", + async () => { + // We run the built JS file using node + const cmd = `node ${BIN_PATH} --input ${testDir} --output ${outputDir} --verbose`; + + try { + const output = await execAsync(cmd); + console.log(output.stdout); + console.error(output.stderr); + } catch (e: any) { + console.error("Bundler failed:", e.stdout, e.stderr); + throw e; + } + + // Check if output exists + const dartFile = join(outputDir, outputFileName); + + // We expect the file to exist. + // Use access to check existence + await expect(access(dartFile, constants.F_OK)).resolves.toBeUndefined(); + }, + timeout + ); + + it("should generate nested files", async () => { + const nestedFolder = "nested"; + await mkdir(join(testDir, nestedFolder), { recursive: true }); + await writeFile(join(testDir, nestedFolder, fileName), validFileContent); + await writeFile(join(testDir, fileName), validFileContent); + + // We run the built JS file using node + const cmd = `node ${BIN_PATH} --input ${testDir} --output ${outputDir} --verbose`; + + try { + const output = await execAsync(cmd); + console.log(output.stdout); + console.error(output.stderr); + } catch (e: any) { + console.error("Bundler failed:", e.stdout, e.stderr); + throw e; + } + + // Check if output exists + const nestedDartFile = join(outputDir, nestedFolder, outputFileName); + await expect( + access(nestedDartFile, constants.F_OK) + ).resolves.toBeUndefined(); + const dartFile = join(outputDir, outputFileName); + await expect(access(dartFile, constants.F_OK)).resolves.toBeUndefined(); + }); +}); diff --git a/packages/globe_runtime_ts/dart_source_generator/test/src/ast-parser.test.ts b/packages/globe_runtime_ts/dart_source_generator/test/src/ast-parser.test.ts new file mode 100644 index 0000000..cbe6989 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/test/src/ast-parser.test.ts @@ -0,0 +1,912 @@ +import { describe, it, expect } from "vitest"; +import { + parseInitArgsAndFunctions, + hasSdkDeclaration, + parseDeclarationFile, + parseTypeAliasMap, +} from "../../src/ast-parser"; +import ts from "typescript"; +import fs from "fs"; +import path from "path"; +import os from "os"; + +// Helper to fully mock the environment for ast-parser which expects a real Program/TypeChecker +function parseCode(code: string) { + const fileName = "test.d.ts"; + const sourceFile = ts.createSourceFile( + fileName, + code, + ts.ScriptTarget.Latest, + true + ); + const defaultCompilerHost = ts.createCompilerHost({}); + + const customCompilerHost = { + ...defaultCompilerHost, + getSourceFile: (name: string, languageVersion: ts.ScriptTarget) => { + if (name === fileName) return sourceFile; + return defaultCompilerHost.getSourceFile(name, languageVersion); + }, + readFile: (name: string) => { + if (name === fileName) return code; + return defaultCompilerHost.readFile(name); + }, + fileExists: (name: string) => { + if (name === fileName) return true; + return defaultCompilerHost.fileExists(name); + }, + }; + + const program = ts.createProgram( + [fileName], + { noLib: true }, + customCompilerHost + ); + const checker = program.getTypeChecker(); + const sf = program.getSourceFile(fileName)!; + + return { sf, checker }; +} + +describe("ast-parser", () => { + describe("parseInitArgsAndFunctions", () => { + it("should parse simple init args and functions with DartReturn", () => { + const code = ` + declare const _default: Sdk<(arg1: string, arg2: number) => any, { + hello: (state: any, name: string, callbackId: number) => DartReturn; + }>; + + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initArgs).toHaveLength(2); + expect(result.initArgs[0].type.dart).toBe("String"); + expect(result.initArgs[1].type.dart).toBe("num"); + + expect(result.functions).toHaveLength(1); + const [hello] = result.functions; + expect(hello.name).toBe("hello"); + expect(hello.dartName).toBe("hello"); + expect(hello.args).toHaveLength(1); + expect(hello.args[0].name).toBe("name"); + expect(hello.args[0].type.dart).toBe("String"); + expect(hello.returnType.dart).toBe("String"); + expect(hello.isStream).toBe(false); + }); + + it("should parse streaming functions with DartStreamReturn", () => { + const code = ` + declare const _default: Sdk<() => void, { + streamData: (state: any, count: number, callbackId: number) => DartStreamReturn; + }>; + + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions).toHaveLength(1); + const [streamData] = result.functions; + expect(streamData.name).toBe("streamData"); + expect(streamData.returnType.dart).toBe("String"); + expect(streamData.isStream).toBe(true); + expect(streamData.args).toHaveLength(1); + expect(streamData.args[0].name).toBe("count"); + expect(streamData.args[0].type.dart).toBe("num"); + }); + + it("should handle multiple functions with mixed return types", () => { + const code = ` + declare const _default: Sdk<() => void, { + getString: (state: any, callbackId: number) => DartReturn; + getNumber: (state: any, callbackId: number) => DartReturn; + streamStrings: (state: any, callbackId: number) => DartStreamReturn; + getBoolean: (state: any, callbackId: number) => DartReturn; + }>; + + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions).toHaveLength(4); + + expect(result.functions[0].name).toBe("getString"); + expect(result.functions[0].returnType.dart).toBe("String"); + expect(result.functions[0].isStream).toBe(false); + + expect(result.functions[1].name).toBe("getNumber"); + expect(result.functions[1].returnType.dart).toBe("num"); + expect(result.functions[1].isStream).toBe(false); + + expect(result.functions[2].name).toBe("streamStrings"); + expect(result.functions[2].returnType.dart).toBe("String"); + expect(result.functions[2].isStream).toBe(true); + + expect(result.functions[3].name).toBe("getBoolean"); + expect(result.functions[3].returnType.dart).toBe("bool"); + expect(result.functions[3].isStream).toBe(false); + }); + + it("should handle named tuples", () => { + const code = ` + declare const _default: Sdk<(apiKey: string, timeout: number) => any, {}>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initArgs).toHaveLength(2); + expect(result.initArgs[0].name).toBe("apiKey"); + expect(result.initArgs[1].name).toBe("timeout"); + }); + + it("should handle snake_case to camelCase conversion", () => { + const code = ` + declare const _default: Sdk<(api_key: string) => any, { + get_user_data: (state: any, user_id: string, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initArgs[0].name).toBe("apiKey"); + expect(result.functions[0].dartName).toBe("getUserData"); + expect(result.functions[0].args[0].name).toBe("userId"); + }); + + it("should handle functions with no arguments (only state and callbackId)", () => { + const code = ` + declare const _default: Sdk<() => void, { + noArgs: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].args).toHaveLength(0); + }); + + it("should handle functions with multiple arguments", () => { + const code = ` + declare const _default: Sdk<() => void, { + multipleArgs: (state: any, a: string, b: number, c: boolean, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].args).toHaveLength(3); + expect(result.functions[0].args[0].type.dart).toBe("String"); + expect(result.functions[0].args[1].type.dart).toBe("num"); + expect(result.functions[0].args[2].type.dart).toBe("bool"); + }); + + it("should handle void return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + doSomething: (state: any, callbackId: number) => void; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("void"); + expect(result.functions[0].isStream).toBe(false); + }); + + it("should handle Uint8Array return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + getBytes: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List"); + }); + + it("should handle DartMap return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + getMap: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("Map"); + expect(result.functions[0].returnType.ffi).toBe("FFIJsonPayload"); + }); + + it("should handle DartList return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + getList: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List"); + expect(result.functions[0].returnType.ffi).toBe("FFIJsonPayload"); + }); + + it("should handle DartSet return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + getSet: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("Set"); + expect(result.functions[0].returnType.ffi).toBe("FFIJsonPayload"); + }); + + it("should handle streaming DartMap", () => { + const code = ` + declare const _default: Sdk<() => void, { + streamMaps: (state: any, callbackId: number) => DartStreamReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("Map"); + expect(result.functions[0].returnType.ffi).toBe("FFIJsonPayload"); + expect(result.functions[0].isStream).toBe(true); + }); + + it("should handle streaming DartList", () => { + const code = ` + declare const _default: Sdk<() => void, { + streamLists: (state: any, callbackId: number) => DartStreamReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List"); + expect(result.functions[0].returnType.ffi).toBe("FFIJsonPayload"); + expect(result.functions[0].isStream).toBe(true); + }); + + it("should handle streaming DartSet", () => { + const code = ` + declare const _default: Sdk<() => void, { + streamSets: (state: any, callbackId: number) => DartStreamReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("Set"); + expect(result.functions[0].returnType.ffi).toBe("FFIJsonPayload"); + expect(result.functions[0].isStream).toBe(true); + }); + + it("should handle array function return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + getArray: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List"); + expect(result.functions[0].isStream).toBe(false); + }); + + it("should handle array function args", () => { + const code = ` + declare const _default: Sdk<() => void, { + getArray: (state: any, array: string[], callbackId: number) => DartReturn; + }>; + export { _default as default };`; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].args).toHaveLength(1); + expect(result.functions[0].args[0].type.dart).toBe("List"); + }); + + it("should handle Array generic syntax", () => { + const code = ` + declare const _default: Sdk<() => void, { + getNumbers: (state: any, callbackId: number) => DartReturn>; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List"); + }); + + it("should handle nested arrays", () => { + const code = ` + declare const _default: Sdk<() => void, { + getMatrix: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List>"); + }); + + it("should handle streaming arrays", () => { + const code = ` + declare const _default: Sdk<() => void, { + streamArrays: (state: any, callbackId: number) => DartStreamReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("List"); + expect(result.functions[0].isStream).toBe(true); + }); + + it("should resolve type aliases in init args", () => { + const code = ` + type MyString = string; + type MyNumber = number; + declare const _default: Sdk<(arg1: MyString, arg2: MyNumber) => any, {}>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initArgs[0].type.dart).toBe("String"); + expect(result.initArgs[1].type.dart).toBe("num"); + }); + + it("should resolve type aliases in function arguments", () => { + const code = ` + type UserId = string; + declare const _default: Sdk<() => void, { + getUser: (state: any, id: UserId, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].args[0].type.dart).toBe("String"); + }); + + it("should resolve type aliases in return types", () => { + const code = ` + type ResponseData = string; + declare const _default: Sdk<() => void, { + getData: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions[0].returnType.dart).toBe("String"); + }); + }); + + describe("hasSdkDeclaration", () => { + it("should return true for valid SDK declaration", () => { + const code = ` + declare const _default: Sdk<[], any, {}>; + export { _default as default }; + `; + const { sf } = parseCode(code); + expect(hasSdkDeclaration(sf)).toBe(true); + }); + + it("should return false for invalid SDK declaration", () => { + const code = ` + export const foo = 1; + `; + const { sf } = parseCode(code); + expect(hasSdkDeclaration(sf)).toBe(false); + }); + + it("should return false for wrong export name", () => { + const code = ` + declare const someOtherName: Sdk<() => void, {}>; + export { someOtherName as default }; + `; + const { sf } = parseCode(code); + expect(hasSdkDeclaration(sf)).toBe(false); + }); + + it("should return false for missing type arguments", () => { + const code = ` + declare const _default: Sdk; + export { _default as default }; + `; + const { sf } = parseCode(code); + expect(hasSdkDeclaration(sf)).toBe(false); + }); + + it("should return false for insufficient type arguments", () => { + const code = ` + declare const _default: Sdk<() => void>; + export { _default as default }; + `; + const { sf } = parseCode(code); + expect(hasSdkDeclaration(sf)).toBe(false); + }); + }); + + describe("parseDeclarationFile", () => { + it("should parse a file from disk with type aliases", () => { + const tmpDir = os.tmpdir(); + const filePath = path.join(tmpDir, `test-${Date.now()}.d.ts`); + const code = ` + type MyType = string; + declare const _default: Sdk<(arg: MyType) => any, { + foo: (state: any, arg: MyType, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + fs.writeFileSync(filePath, code); + + try { + const result = parseDeclarationFile(filePath); + expect(result).not.toBeNull(); + expect(result!.initArgs).toHaveLength(1); + expect(result!.initArgs[0].type.dart).toBe("String"); + expect(result!.functions).toHaveLength(1); + expect(result!.functions[0].name).toBe("foo"); + expect(result!.functions[0].returnType.dart).toBe("num"); + expect(result!.functions[0].isStream).toBe(false); + } finally { + fs.unlinkSync(filePath); + } + }); + + it("should parse a file with streaming functions", () => { + const tmpDir = os.tmpdir(); + const filePath = path.join(tmpDir, `test-stream-${Date.now()}.d.ts`); + const code = ` + declare const _default: Sdk<() => void, { + streamData: (state: any, callbackId: number) => DartStreamReturn; + }>; + export { _default as default }; + `; + fs.writeFileSync(filePath, code); + + try { + const result = parseDeclarationFile(filePath); + expect(result).not.toBeNull(); + expect(result!.functions).toHaveLength(1); + expect(result!.functions[0].isStream).toBe(true); + } finally { + fs.unlinkSync(filePath); + } + }); + + it("should return null for invalid file path", () => { + expect(() => parseDeclarationFile("/non/existent/path.d.ts")).toThrow(); + }); + + it("should return null for malformed SDK declaration", () => { + const tmpDir = os.tmpdir(); + const filePath = path.join(tmpDir, `test-malformed-${Date.now()}.d.ts`); + const code = ` + declare const _default: SomethingElse; + export { _default as default }; + `; + fs.writeFileSync(filePath, code); + + try { + const result = parseDeclarationFile(filePath); + expect(result).toBeNull(); + } finally { + fs.unlinkSync(filePath); + } + }); + }); + + describe("parseTypeAliasMap", () => { + it("should parse simple type aliases", () => { + const code = ` + type MyString = string; + type MyNumber = number; + `; + const { sf } = parseCode(code); + const map = parseTypeAliasMap(sf); + + expect(map.size).toBe(2); + expect(map.has("MyString")).toBe(true); + expect(map.has("MyNumber")).toBe(true); + }); + + it("should parse complex type aliases", () => { + const code = ` + type UserId = string; + type User = { id: UserId; name: string }; + `; + const { sf } = parseCode(code); + const map = parseTypeAliasMap(sf); + + expect(map.size).toBe(2); + expect(map.has("UserId")).toBe(true); + expect(map.has("User")).toBe(true); + }); + + it("should handle empty source file", () => { + const code = ``; + const { sf } = parseCode(code); + const map = parseTypeAliasMap(sf); + + expect(map.size).toBe(0); + }); + }); + + describe("edge cases", () => { + it("should handle empty init args", () => { + const code = ` + declare const _default: Sdk<() => void, { + test: (state: any, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initArgs).toHaveLength(0); + }); + + it("should handle empty functions object", () => { + const code = ` + declare const _default: Sdk<() => void, {}>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions).toHaveLength(0); + }); + + it("should handle nested type aliases", () => { + const code = ` + type InnerType = string; + type OuterType = InnerType; + declare const _default: Sdk<(arg: OuterType) => any, {}>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initArgs[0].type.dart).toBe("String"); + }); + + it("should handle functions with Promise return type", () => { + const code = ` + declare const _default: Sdk<() => void, { + asyncFunc: (state: any, callbackId: number) => Promise; + }>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + // Promise should be treated as void return + expect(result.functions[0].returnType.dart).toBe("dynamic"); + }); + + it("should handle namespaced DartReturn types (tsdown bundler)", () => { + const code = ` + declare const _default: Sdk<() => void, { + getString: (state: any, callbackId: number) => _globe_runtime_types0.DartReturn; + getMap: (state: any, callbackId: number) => _globe_runtime_types0.DartReturn<_globe_runtime_types0.DartMap>; + }>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions).toHaveLength(2); + expect(result.functions[0].returnType.dart).toBe("String"); + expect(result.functions[1].returnType.dart).toBe("Map"); + }); + + it("should handle namespaced DartStreamReturn types (tsdown bundler)", () => { + const code = ` + declare const _default: Sdk<() => void, { + streamString: (state: any, callbackId: number) => _namespace.DartStreamReturn; + streamList: (state: any, callbackId: number) => _namespace.DartStreamReturn<_namespace.DartList>; + }>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions).toHaveLength(2); + expect(result.functions[0].returnType.dart).toBe("String"); + expect(result.functions[0].isStream).toBe(true); + expect(result.functions[1].returnType.dart).toBe("List"); + expect(result.functions[1].isStream).toBe(true); + }); + + it("should handle all namespaced collection types", () => { + const code = ` + declare const _default: Sdk<() => void, { + getMap: (state: any, callbackId: number) => _types.DartReturn<_types.DartMap>; + getList: (state: any, callbackId: number) => _types.DartReturn<_types.DartList>; + getSet: (state: any, callbackId: number) => _types.DartReturn<_types.DartSet>; + }>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.functions).toHaveLength(3); + expect(result.functions[0].returnType.dart).toBe("Map"); + expect(result.functions[1].returnType.dart).toBe("List"); + expect(result.functions[2].returnType.dart).toBe("Set"); + }); + + it("should preserve documentation and parameter names in init function", () => { + const code = ` + declare const _default: { + /** + * Initialize the SDK + * @param apiKey - Your API key + * @param timeout - Request timeout + */ + init: (apiKey: string, timeout: number) => any; + } & Sdk<(apiKey: string, timeout: number) => any, { + /** + * Get user data + * @param id - User ID + */ + getUser: (state: any, id: string, callbackId: number) => DartReturn; + }>; + export { _default as default }; + `; + const { sf, checker } = parseCode(code); + const typeAliasMap = parseTypeAliasMap(sf); + + const result = parseInitArgsAndFunctions({ + sourceFile: sf, + checker, + typeAliasMap, + }); + + expect(result.initDescription).toBe("Initialize the SDK"); + expect(result.initArgs).toHaveLength(2); + expect(result.initArgs[0].name).toBe("apiKey"); + expect(result.initArgs[0].description).toBe("Your API key"); + expect(result.initArgs[1].name).toBe("timeout"); + expect(result.initArgs[1].description).toBe("Request timeout"); + + expect(result.functions).toHaveLength(1); + expect(result.functions[0].description).toBe("Get user data"); + expect(result.functions[0].args[0].description).toBe("User ID"); + }); + }); +}); diff --git a/packages/globe_runtime_ts/dart_source_generator/test/src/dart-codegen.test.ts b/packages/globe_runtime_ts/dart_source_generator/test/src/dart-codegen.test.ts new file mode 100644 index 0000000..7acc725 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/test/src/dart-codegen.test.ts @@ -0,0 +1,701 @@ +import { describe, it, expect } from "vitest"; +import { + generateDartClass, + generateStreamValueHandling, +} from "../../src/dart-codegen"; +import { ArgType, FuncType } from "../../src/types"; + +describe("dart-codegen", () => { + describe("generateDartClass", () => { + it("should generate a simple class with no args or functions", () => { + const jsSource = "console.log('hello');"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = []; + const className = "MySdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("class MySdk {"); + expect(result).toContain("const packageVersion = '1.0.0';"); + expect(result).toContain(jsSource); + expect(result).toContain("Future create"); + expect(result).toContain("import 'dart:async';"); + expect(result).toContain("import 'dart:convert';"); + expect(result).toContain( + "import 'package:globe_runtime/globe_runtime.dart';" + ); + expect(result).toContain("void dispose()"); + }); + + it("should generate a class with single init arg", () => { + const jsSource = "function test() {}"; + const initArgs = [ + { name: "apiKey", type: { dart: "String", ffi: "FFIString" } }, + ]; + const functions: FuncType[] = []; + const className = "TestSdk"; + const version = "0.0.1"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("String? apiKey"); + expect(result).toContain("apiKey?.toFFIType"); + expect(result).toContain("Future create({String? apiKey})"); + }); + + it("should generate a class with multiple init args", () => { + const jsSource = "function test() {}"; + const initArgs = [ + { name: "apiKey", type: { dart: "String", ffi: "FFIString" } }, + { name: "timeout", type: { dart: "num", ffi: "FFINumber" } }, + { name: "verbose", type: { dart: "bool", ffi: "FFIBool" } }, + ]; + const functions: FuncType[] = []; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("String? apiKey, num? timeout, bool? verbose"); + expect(result).toContain("apiKey?.toFFIType"); + expect(result).toContain("timeout?.toFFIType"); + expect(result).toContain("verbose?.toFFIType"); + }); + + it("should generate a single-value function returning String", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "hello", + dartName: "hello", + returnType: { dart: "String", ffi: "FFIString" }, + args: [ + { + name: "name", + type: { dart: "String", ffi: "FFIString" }, + }, + ], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "0.0.1"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future hello(String name) async {"); + expect(result).toContain("final completer = Completer();"); + expect(result).toContain("_module.callFunction("); + expect(result).toContain("'hello'"); + expect(result).toContain("args: [name.toFFIType]"); + expect(result).toContain("utf8.decode(value)"); + expect(result).toContain("completer.complete("); + }); + + it("should generate a single-value function with multiple args", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "calculate", + dartName: "calculate", + returnType: { dart: "num", ffi: "FFINumber" }, + args: [ + { name: "a", type: { dart: "num", ffi: "FFINumber" } }, + { name: "b", type: { dart: "num", ffi: "FFINumber" } }, + { name: "operation", type: { dart: "String", ffi: "FFIString" } }, + ], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain( + "Future calculate(num a, num b, String operation) async {" + ); + expect(result).toContain( + "args: [a.toFFIType, b.toFFIType, operation.toFFIType]" + ); + }); + + it("should generate a single-value function with no args", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "get_status", + dartName: "getStatus", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future getStatus() async {"); + expect(result).toContain("args: []"); + }); + + it("should generate a void return function", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "doSomething", + dartName: "doSomething", + returnType: { dart: "void", ffi: "Void" }, + args: [], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future doSomething() async {"); + expect(result).toContain("final completer = Completer();"); + expect(result).toContain("completer.complete();"); + expect(result).not.toContain("utf8.decode"); + expect(result).not.toContain("value as"); + }); + + it("should generate functions with all primitive types", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "getString", + dartName: "getString", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: false, + }, + { + name: "getNumber", + dartName: "getNumber", + returnType: { dart: "num", ffi: "FFINumber" }, + args: [], + isStream: false, + }, + { + name: "getBool", + dartName: "getBool", + returnType: { dart: "bool", ffi: "FFIBool" }, + args: [], + isStream: false, + }, + { + name: "getBytes", + dartName: "getBytes", + returnType: { dart: "List", ffi: "FFIBytes" }, + args: [], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future getString() async {"); + expect(result).toContain("utf8.decode(value)"); + expect(result).toContain("Future getNumber() async {"); + expect(result).toContain("value as num"); + expect(result).toContain("Future getBool() async {"); + expect(result).toContain("value as bool"); + expect(result).toContain("Future> getBytes() async {"); + expect(result).toContain("final value = data.data;"); + }); + + it("should generate functions with collection types", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "getMap", + dartName: "getMap", + returnType: { dart: "Map", ffi: "FFIJsonPayload" }, + args: [], + isStream: false, + }, + { + name: "getList", + dartName: "getList", + returnType: { dart: "List", ffi: "FFIJsonPayload" }, + args: [], + isStream: false, + }, + { + name: "getSet", + dartName: "getSet", + returnType: { dart: "Set", ffi: "FFIJsonPayload" }, + args: [], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future> getMap() async {"); + expect(result).toContain("value as Map"); + expect(result).toContain("Future> getList() async {"); + expect(result).toContain("value as List"); + expect(result).toContain("Future> getSet() async {"); + expect(result).toContain("Set.from(value)"); + }); + + it("should generate streaming function", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "streamData", + dartName: "streamData", + returnType: { dart: "String", ffi: "FFIString" }, + args: [{ name: "count", type: { dart: "num", ffi: "FFINumber" } }], + isStream: true, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Stream streamData(num count) {"); + expect(result).toContain( + "final controller = StreamController();" + ); + expect(result).toContain("if (data.hasData()) {"); + expect(result).toContain("controller.add("); + expect(result).toContain("if (data.done) {"); + expect(result).toContain("controller.close();"); + expect(result).toContain("return false; // Keep listening for more data"); + expect(result).not.toContain("completer"); + }); + + it("should generate multiple streaming functions", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "streamStrings", + dartName: "streamStrings", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: true, + }, + { + name: "streamNumbers", + dartName: "streamNumbers", + returnType: { dart: "num", ffi: "FFINumber" }, + args: [], + isStream: true, + }, + { + name: "streamMaps", + dartName: "streamMaps", + returnType: { dart: "Map", ffi: "FFIJsonPayload" }, + args: [], + isStream: true, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Stream streamStrings() {"); + expect(result).toContain("Stream streamNumbers() {"); + expect(result).toContain("Stream> streamMaps() {"); + }); + + it("should generate mixed single-value and streaming functions", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "getValue", + dartName: "getValue", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: false, + }, + { + name: "streamValue", + dartName: "streamValue", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: true, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future getValue() async {"); + expect(result).toContain("Stream streamValue() {"); + expect(result).toContain("final completer = Completer();"); + expect(result).toContain( + "final controller = StreamController();" + ); + }); + + it("should handle snake_case to camelCase conversion in function names", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "get_user_data", + dartName: "getUserData", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future getUserData() async {"); + expect(result).toContain("'get_user_data'"); + }); + + it("should handle error cases in single-value functions", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "test", + dartName: "test", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: false, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("if (data.hasError()) {"); + expect(result).toContain("completer.completeError(data.error);"); + }); + + it("should handle error cases in streaming functions", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "test", + dartName: "test", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + isStream: true, + }, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("if (data.hasError()) {"); + expect(result).toContain("controller.addError(data.error);"); + expect(result).toContain("return true;"); + }); + + it("should properly escape JavaScript source code", () => { + const jsSource = "const str = r'''multi\nline\nstring''';"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = []; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("const packageSource = r'''"); + expect(result).toContain(jsSource); + expect(result).toContain("''';"); + }); + }); + + describe("generateStreamValueHandling", () => { + it("should handle String type", () => { + const result = generateStreamValueHandling("String"); + expect(result).toContain("if (data.hasData()) {"); + expect(result).toContain("final value = data.data;"); + expect(result).toContain("utf8.decode(value)"); + expect(result).toContain("controller.add("); + expect(result).toContain("if (data.done) {"); + expect(result).toContain("controller.close();"); + }); + + it("should handle List type", () => { + const result = generateStreamValueHandling("List"); + expect(result).toContain("if (data.hasData()) {"); + expect(result).toContain("final value = data.data;"); + expect(result).toContain("controller.add(value);"); + expect(result).toContain("if (data.done) {"); + expect(result).toContain("controller.close();"); + expect(result).not.toContain(".unpack()"); + }); + + it("should handle Set type", () => { + const result = generateStreamValueHandling("Set"); + expect(result).toContain("if (data.hasData()) {"); + expect(result).toContain("final value = data.data.unpack();"); + expect(result).toContain("Set.from(value)"); + expect(result).toContain("controller.add("); + expect(result).toContain("if (data.done) {"); + expect(result).toContain("controller.close();"); + }); + + it("should handle num type", () => { + const result = generateStreamValueHandling("num"); + expect(result).toContain("value as num"); + }); + + it("should handle bool type", () => { + const result = generateStreamValueHandling("bool"); + expect(result).toContain("value as bool"); + }); + + it("should handle Map type", () => { + const result = generateStreamValueHandling("Map"); + expect(result).toContain("value as Map"); + }); + + it("should handle List type", () => { + const result = generateStreamValueHandling("List"); + expect(result).toContain("value as List"); + }); + + it("should handle custom types", () => { + const result = generateStreamValueHandling("CustomType"); + expect(result).toContain("value as CustomType"); + }); + }); + + describe("edge cases", () => { + it("should handle empty init args array", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = []; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("Future create() async {"); + expect(result).toContain( + "await module.register(args: [\n \n ]);" + ); + }); + + it("should handle empty functions array", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = []; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("class TestSdk {"); + expect(result).toContain("void dispose() {"); + // Should not have any function definitions after dispose + const disposeIndex = result.indexOf("void dispose()"); + const afterDispose = result.substring(disposeIndex + 100); + expect(afterDispose.match(/Future { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = []; + const className = "TestSdk"; + const version = "1.0.0-beta.1+build.123"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain( + "const packageVersion = '1.0.0-beta.1+build.123';" + ); + }); + + it("should handle class names with numbers", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = []; + const className = "MySdk2"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + expect(result).toContain("class MySdk2 {"); + expect(result).toContain("Future create"); + expect(result).toContain("return MySdk2._(module);"); + }); + + it("should handle functions with isStream undefined", () => { + const jsSource = "function test() {}"; + const initArgs: ArgType[] = []; + const functions: FuncType[] = [ + { + name: "test", + dartName: "test", + returnType: { dart: "String", ffi: "FFIString" }, + args: [], + // isStream is undefined + } as any, + ]; + const className = "TestSdk"; + const version = "1.0.0"; + + const result = generateDartClass({ + className, + version, + jsSource, + initArgs, + functions, + }); + + // Should default to single-value function + expect(result).toContain("Future test() async {"); + expect(result).toContain("final completer = Completer();"); + }); + }); +}); diff --git a/packages/globe_runtime_ts/dart_source_generator/test/src/type-mapper-checker.test.ts b/packages/globe_runtime_ts/dart_source_generator/test/src/type-mapper-checker.test.ts new file mode 100644 index 0000000..eea0b1e --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/test/src/type-mapper-checker.test.ts @@ -0,0 +1,207 @@ +import { describe, it, expect } from "vitest"; +import { mapTsTypeToDart } from "../../src/type-mapper"; +import ts from "typescript"; + +// Helper to fully mock the environment for type-mapper with checker +function createTypeCheckerEnvironment(code: string) { + const fileName = "test.ts"; + const sourceFile = ts.createSourceFile( + fileName, + code, + ts.ScriptTarget.Latest + ); + const defaultCompilerHost = ts.createCompilerHost({}); + + const customCompilerHost = { + ...defaultCompilerHost, + getSourceFile: (name: string, languageVersion: ts.ScriptTarget) => { + if (name === fileName) return sourceFile; + return defaultCompilerHost.getSourceFile(name, languageVersion); + }, + readFile: (name: string) => { + if (name === fileName) return code; + return defaultCompilerHost.readFile(name); + }, + fileExists: (name: string) => { + if (name === fileName) return true; + return defaultCompilerHost.fileExists(name); + }, + }; + + const program = ts.createProgram( + [fileName], + { noLib: true, strict: true }, + customCompilerHost + ); + const checker = program.getTypeChecker(); + const sf = program.getSourceFile(fileName)!; + + return { sf, checker }; +} + +function getTypeNodeFromCode(sourceFile: ts.SourceFile): ts.TypeNode { + // Assumes the code has `type T = ...` or similar as first statement + const stmt = sourceFile.statements[0]; + if (ts.isTypeAliasDeclaration(stmt)) { + return stmt.type; + } + // Or if it's `const x: T = ...` + if (ts.isVariableStatement(stmt)) { + return stmt.declarationList.declarations[0].type!; + } + throw new Error("Could not find type node in test definition"); +} + +describe("type-mapper with checker", () => { + it("should resolve type aliases via checker", () => { + const code = ` + type MyString = string; + type T = MyString; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + // The type node for 'T' depends on 'MyString' + // 'T' is the second statement + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("String"); + }); + + it("should resolve unions via checker", () => { + const code = ` + type A = string; + type B = number; + type T = A | B; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[2] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + // string | number -> dynamic + expect(result.dart).toBe("dynamic"); + }); + + it("should resolve single type union via checker", () => { + const code = ` + type A = string; + type T = A | undefined; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("String"); + }); + + it("should resolve string literal union via checker", () => { + const code = ` + type T = "a" | "b"; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[0] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("String"); + }); + + it("should resolve boolean via checker", () => { + const code = ` + type MyBool = boolean; + type T = MyBool; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("bool"); + }); + + it("should resolve number via checker", () => { + const code = ` + type MyNum = number; + type T = MyNum; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("num"); + }); + + it("should resolve qualified names", () => { + // To cover getEntityName recursion and complex access + const code = ` + namespace A { + export namespace B { + export type C = string; + } + } + type T = A.B.C; + `; + // We need map to support this or checker. + // mapTsTypeToDart uses getEntityName when using typeAliasMap. + // Let's test getEntityName via mapTsTypeToDart with a map key that matches qualified name. + + // Note: TypeScript might simplify A.B.C to just C if we used checker, + // but here we want to test getEntityName logic in mapTsTypeToDart when typeAliasMap is present. + + // We can manually construct a node that has a QualifiedName for typeName + // But harder to do with createSourceFile only. + // Actually `type T = A.B.C` creates a TypeReferenceNode with typeName as QualifiedName. + + const { sf } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + + const aliasMap = new Map(); + const stringNode = ts.factory.createKeywordTypeNode( + ts.SyntaxKind.StringKeyword + ); + aliasMap.set("A.B.C", stringNode); // We assume getEntityName returns dotted path + + const result = mapTsTypeToDart(tStmt.type, undefined, aliasMap); + expect(result.dart).toBe("String"); + }); + + it("should resolve alias to union via checker", () => { + const code = ` + type MyUnion = string | undefined; + type T = MyUnion; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("String"); + }); + + it("should resolve alias to literal union via checker", () => { + const code = ` + type MyUnion = "a" | "b"; + type T = MyUnion; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[1] as ts.TypeAliasDeclaration; + const result = mapTsTypeToDart(tStmt.type, checker); + expect(result.dart).toBe("String"); + }); + + it("should resolve alias to num/bool union via checker", () => { + // Covers lines 68-78 (num), 80-84 (bool) if we have single type + const code = ` + type NumUnion = number | undefined; + type BoolUnion = boolean | null; + type T1 = NumUnion; + type T2 = BoolUnion; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + + const t1 = (sf.statements[2] as ts.TypeAliasDeclaration).type; + expect(mapTsTypeToDart(t1, checker).dart).toBe("num"); + + const t2 = (sf.statements[3] as ts.TypeAliasDeclaration).type; + expect(mapTsTypeToDart(t2, checker).dart).toBe("bool"); + }); + + it("should resolve single BooleanLiteral union (true | undefined) via checker", () => { + // should hit the length === 1 boolean check + const code = ` + type T = true | undefined; + `; + const { sf, checker } = createTypeCheckerEnvironment(code); + const tStmt = sf.statements[0] as ts.TypeAliasDeclaration; + expect(mapTsTypeToDart(tStmt.type, checker).dart).toBe("bool"); + }); +}); diff --git a/packages/globe_runtime_ts/dart_source_generator/test/src/type-mapper.test.ts b/packages/globe_runtime_ts/dart_source_generator/test/src/type-mapper.test.ts new file mode 100644 index 0000000..741a329 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/test/src/type-mapper.test.ts @@ -0,0 +1,107 @@ +import { describe, it, expect } from "vitest"; +import { mapTsTypeToDart } from "../../src/type-mapper"; +import ts from "typescript"; + +function createTypeNode(code: string): ts.TypeNode { + const sourceFile = ts.createSourceFile( + "test.ts", + `type T = ${code};`, + ts.ScriptTarget.Latest + ); + const typeAlias = sourceFile.statements[0] as ts.TypeAliasDeclaration; + return typeAlias.type; +} + +describe("type-mapper", () => { + it("should map primitive types", () => { + expect(mapTsTypeToDart(createTypeNode("string")).dart).toBe("String"); + expect(mapTsTypeToDart(createTypeNode("number")).dart).toBe("num"); + expect(mapTsTypeToDart(createTypeNode("boolean")).dart).toBe("bool"); + }); + + it("should map String types/literals", () => { + expect(mapTsTypeToDart(createTypeNode("'hello'")).dart).toBe("String"); + }); + + it("should map Uint8Array to List", () => { + // Note: This relies on type reference name matching string "Uint8Array" + // in the simplified mapper logic. + expect(mapTsTypeToDart(createTypeNode("Uint8Array")).dart).toBe( + "List" + ); + }); + + it("should map unknown/void/dynamic", () => { + expect(mapTsTypeToDart(createTypeNode("any")).dart).toBe("dynamic"); + expect(mapTsTypeToDart(createTypeNode("void")).dart).toBe("void"); + // void usually maps to dynamic in the mapper logic unless specific handling + }); + + it("should handle union types", () => { + // string | undefined -> String (non-nullable extraction logic) + expect(mapTsTypeToDart(createTypeNode("string | undefined")).dart).toBe( + "String" + ); + + // string | null -> String + expect(mapTsTypeToDart(createTypeNode("string | null")).dart).toBe( + "String" + ); + + // string | number -> dynamic (fallback) + expect(mapTsTypeToDart(createTypeNode("string | number")).dart).toBe( + "dynamic" + ); + + // "a" | "b" -> String (all string literals) + expect(mapTsTypeToDart(createTypeNode("'a' | 'b'")).dart).toBe("String"); + + // "a" | 1 -> dynamic (mixed literals) + expect(mapTsTypeToDart(createTypeNode("'a' | 1")).dart).toBe("dynamic"); + }); + + it("should resolve type aliases", () => { + const aliasMap = new Map(); + aliasMap.set("MyString", createTypeNode("string")); + aliasMap.set("MyNumber", createTypeNode("number")); + aliasMap.set("Recursive", createTypeNode("MyString")); + aliasMap.set("DartMap", createTypeNode("{ __dartType: 'Map' }")); + aliasMap.set("DartSet", createTypeNode("{ __dartType: 'Set' }")); + aliasMap.set("DartList", createTypeNode("{ __dartType: 'List' }")); + + // Direct alias + expect( + mapTsTypeToDart(createTypeNode("MyString"), undefined, aliasMap).dart + ).toBe("String"); + + // Recursive alias + expect( + mapTsTypeToDart(createTypeNode("Recursive"), undefined, aliasMap).dart + ).toBe("String"); + + // DartMap alias + expect( + mapTsTypeToDart(createTypeNode("DartMap"), undefined, aliasMap).dart + ).toBe("Map"); + + // DartSet alias + expect( + mapTsTypeToDart(createTypeNode("DartSet"), undefined, aliasMap).dart + ).toBe("Set"); + + // DartList alias + expect( + mapTsTypeToDart(createTypeNode("DartList"), undefined, aliasMap).dart + ).toBe("List"); + }); + + it("should handle number and boolean literals", () => { + expect(mapTsTypeToDart(createTypeNode("1")).dart).toBe("num"); + expect(mapTsTypeToDart(createTypeNode("true")).dart).toBe("bool"); + }); + + it("should handle unhandled literals (BigInt) as dynamic", () => { + // BigInt literal "100n" + expect(mapTsTypeToDart(createTypeNode("100n")).dart).toBe("dynamic"); + }); +}); diff --git a/packages/globe_runtime_ts/dart_source_generator/test/tsconfig.json b/packages/globe_runtime_ts/dart_source_generator/test/tsconfig.json new file mode 100644 index 0000000..d8dc8c8 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/test/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "noEmit": true, + "rootDir": "../", + }, + "include": ["../src/**/*.ts", "**/*.test.ts"], + "exclude": ["node_modules"] +} diff --git a/packages/globe_runtime_ts/dart_source_generator/tsconfig.json b/packages/globe_runtime_ts/dart_source_generator/tsconfig.json new file mode 100644 index 0000000..83cc341 --- /dev/null +++ b/packages/globe_runtime_ts/dart_source_generator/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "CommonJS", + "lib": ["ES2020", "ES2015", "DOM"], + "moduleResolution": "node", + "declaration": true, + "outDir": "./dist", + "rootDir": "./", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "node_modules", + "**/*.spec.ts", + "**/*.test.ts", + "dist" + ], + "types": ["node"] +} diff --git a/packages/globe_runtime_ts/index.d.ts b/packages/globe_runtime_ts/index.d.ts deleted file mode 100644 index 47d08ee..0000000 --- a/packages/globe_runtime_ts/index.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -declare global { - - type DartValue = Uint8Array | undefined; - - interface DartGlobal { - /** - * Sends data back to Dart from JavaScript. - * - * @param callbackId - A unique identifier for the callback. - * @param data - The data to send. - * @returns {boolean} - Returns true if the data was sent successfully. - */ - send_value: (callbackId: number, data: DartValue) => boolean; - - /** - * Sends an error message back to Dart from JavaScript. - * - * @param callbackId - A unique identifier for the callback. - * @param error - The error message to send. - */ - send_error: (callbackId: number, error: string) => boolean; - - /** - * Sends data back to Dart from JavaScript. - * - * @param callbackId - A unique identifier for the callback. - * @param data - The data to send. - * @returns {boolean} - Returns true if the data was sent successfully. - */ - stream_value: (callbackId: number, data: DartValue) => boolean; - - /** - * Sends data back to Dart from JavaScript. - * - * @param callbackId - A unique identifier for the callback. - * @param data - The data to send. - * @returns {boolean} - Returns true if the data was sent successfully. - */ - stream_value_end: ( - callbackId: number, - data?:DartValue - ) => boolean; - } - - const Dart: DartGlobal; - - const JsonPayload: { - // Encoding payload using MessagePack - encode(value: unknown): DartValue; - // Decoding payload using MessagePack - decode(value: Uint8Array): any; - }; -} - -export {}; diff --git a/packages/globe_runtime_ts/runtime_types/LICENSE b/packages/globe_runtime_ts/runtime_types/LICENSE new file mode 100644 index 0000000..6845152 --- /dev/null +++ b/packages/globe_runtime_ts/runtime_types/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2023-present Invertase Limited + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/packages/globe_runtime_ts/runtime_types/README.md b/packages/globe_runtime_ts/runtime_types/README.md new file mode 100644 index 0000000..c946ae9 --- /dev/null +++ b/packages/globe_runtime_ts/runtime_types/README.md @@ -0,0 +1,366 @@ +# Globe Runtime Types (@globe/runtime_types) + +Type definitions and helpers for building Globe runtime SDKs. This package provides TypeScript utilities for defining strongly-typed SDKs that communicate with the Globe Dart runtime. + +## Overview + +`@globe/runtime_types` is used in conjunction with the Globe runtime to create JavaScript/TypeScript SDKs that can be called from Dart/Flutter applications. It provides type-safe wrappers for defining functions that return single values or streams, along with global Dart interop APIs. + +## Installation + +```bash +npm install @globe/runtime_types +``` + +## Core Concepts + +### Module State + +Your SDK maintains state that is initialized once and passed to all functions. Define your state type based on what data your functions need: + +```typescript +type ModuleState = { + apiUrl: string; + timeout: number; + userId: string; +}; +``` + +### Worker Functions + +Worker functions are async functions that receive: +- **state**: The object returned from `init()` +- **args**: Arguments passed from Dart (excluding callbackId) +- **callbackId**: A unique identifier for the callback (always last parameter) + +Functions must not return values directly. Instead, they send data back to Dart using the `Dart` global object. + +## API Reference + +### SDK Definition + +#### `defineSdk(definition)` + +Define a typed SDK with initialization and functions. + +```typescript +export default defineSdk({ + init(apiUrl: string = "https://api.example.com", timeout: number = 5000): ModuleState { + return { apiUrl, timeout }; + }, + functions: { + fetchUsers, + calculatePrice, + streamData, + }, +}); +``` + +### Single Value Return Helpers + +These helpers define functions that send a single value back to Dart. + +#### `returnString(fn)` + +Returns a string to Dart (Dart: `String`, JS: `string`). + +```typescript +const fetchUser = returnString( + async (state: ModuleState, userId: string, callbackId: number) => { + const url = `${state.apiUrl}/users/${userId}`; + const response = await fetch(url); + const user = await response.json(); + Dart.send_value(callbackId, new TextEncoder().encode(JSON.stringify(user))); + } +); +``` + +#### `returnInt(fn)` + +Returns an integer to Dart (Dart: `int`, JS: `number`). + +```typescript +const calculateSum = returnInt( + (state: ModuleState, a: number, b: number, callbackId: number) => { + const result = Math.floor(a + b); + Dart.send_value(callbackId, new TextEncoder().encode(result.toString())); + } +); +``` + +#### `returnDouble(fn)` + +Returns a double-precision number to Dart (Dart: `double`, JS: `number`). + +```typescript +const calculateAverage = returnDouble( + (state: ModuleState, values: number[], callbackId: number) => { + const avg = values.reduce((a, b) => a + b, 0) / values.length; + Dart.send_value(callbackId, new TextEncoder().encode(avg.toString())); + } +); +``` + +#### `returnNumber(fn)` + +Returns a generic number to Dart (Dart: `num`, JS: `number`). + +#### `returnBoolean(fn)` + +Returns a boolean to Dart (Dart: `bool`, JS: `boolean`). + +```typescript +const isValid = returnBoolean( + (state: ModuleState, value: string, callbackId: number) => { + const valid = value.length > 0; + Dart.send_value(callbackId, JsonPayload.encode(valid)!); + } +); +``` + +#### `returnUint8Array(fn)` + +Returns binary data to Dart (Dart: `List`, JS: `Uint8Array`). + +```typescript +const generateBytes = returnUint8Array( + (state: ModuleState, length: number, callbackId: number) => { + const bytes = new Uint8Array(length); + for (let i = 0; i < length; i++) { + bytes[i] = Math.floor(Math.random() * 256); + } + Dart.send_value(callbackId, bytes); + } +); +``` + +#### `returnMap(fn)` + +Returns a map/object to Dart (Dart: `Map`, JS: `object`). + +```typescript +const getMetadata = returnMap( + (state: ModuleState, id: string, callbackId: number) => { + const metadata = { id, url: state.apiUrl, timestamp: Date.now() }; + const encoded = JsonPayload.encode(metadata); + if (encoded) { + Dart.send_value(callbackId, encoded); + } + } +); +``` + +#### `returnList(fn)` + +Returns a list to Dart (Dart: `List`, JS: `object`). + +```typescript +const getItems = returnList( + (state: ModuleState, count: number, callbackId: number) => { + const items = Array.from({ length: count }, (_, i) => ({ id: i })); + const encoded = JsonPayload.encode(items); + if (encoded) { + Dart.send_value(callbackId, encoded); + } + } +); +``` + +#### `returnSet(fn)` + +Returns a set to Dart (Dart: `Set`, JS: `object`). + +```typescript +const getUniqueValues = returnSet( + (state: ModuleState, values: number[], callbackId: number) => { + const unique = [...new Set(values)]; + const encoded = JsonPayload.encode(unique); + if (encoded) { + Dart.send_value(callbackId, encoded); + } + } +); +``` + +### Streaming Return Helpers + +These helpers define functions that stream multiple values back to Dart. + +#### `streamString(fn)` + +Streams strings to Dart (Dart: `Stream`, JS: `string`). + +```typescript +const streamMessages = streamString( + async (state: ModuleState, callbackId: number) => { + for (let i = 0; i < 5; i++) { + const message = `Message ${i}`; + Dart.stream_value(callbackId, new TextEncoder().encode(message)); + } + Dart.stream_value_end(callbackId); + } +); +``` + +#### `streamInt(fn)` + +Streams integers to Dart (Dart: `Stream`, JS: `number`). + +#### `streamDouble(fn)` + +Streams doubles to Dart (Dart: `Stream`, JS: `number`). + +#### `streamNumber(fn)` + +Streams numbers to Dart (Dart: `Stream`, JS: `number`). + +#### `streamBoolean(fn)` + +Streams booleans to Dart (Dart: `Stream`, JS: `boolean`). + +#### `streamUint8Array(fn)` + +Streams binary data to Dart (Dart: `Stream>`, JS: `Uint8Array`). + +#### `streamMap(fn)` + +Streams maps to Dart (Dart: `Stream>`, JS: `object`). + +```typescript +const streamUpdates = streamMap( + async (state: ModuleState, callbackId: number) => { + for (let i = 0; i < 5; i++) { + const update = { index: i, timestamp: Date.now() }; + const encoded = JsonPayload.encode(update); + if (encoded) { + Dart.stream_value(callbackId, encoded); + } + await new Promise(resolve => setTimeout(resolve, 100)); + } + Dart.stream_value_end(callbackId); + } +); +``` + +#### `streamList(fn)` + +Streams lists to Dart (Dart: `Stream>`, JS: `object`). + +#### `streamSet(fn)` + +Streams sets to Dart (Dart: `Stream>`, JS: `object`). + +### Dart Global APIs + +The `Dart` global object provides methods for sending data back to the Dart runtime: + +#### `Dart.send_value(callbackId, data)` + +Sends a single value to Dart and completes the callback. + +```typescript +Dart.send_value(callbackId, new TextEncoder().encode("result")); +``` + +#### `Dart.send_error(callbackId, error)` + +Sends an error message to Dart and fails the callback. + +```typescript +Dart.send_error(callbackId, "An error occurred"); +``` + +#### `Dart.stream_value(callbackId, data)` + +Sends a value as part of a stream. Use multiple times to emit multiple values. + +```typescript +Dart.stream_value(callbackId, new TextEncoder().encode("chunk1")); +Dart.stream_value(callbackId, new TextEncoder().encode("chunk2")); +``` + +#### `Dart.stream_value_end(callbackId)` + +Completes the stream. Must be called after all values have been sent. + +```typescript +Dart.stream_value_end(callbackId); +``` + +### Payload Encoding + +The `JsonPayload` global provides MessagePack-based encoding for complex data types: + +#### `JsonPayload.encode(value)` + +Encodes a JavaScript object/array to MessagePack bytes. + +```typescript +const encoded = JsonPayload.encode({ key: "value" }); +Dart.send_value(callbackId, encoded!); +``` + +#### `JsonPayload.decode(data)` + +Decodes MessagePack bytes back to JavaScript objects. + +```typescript +const decoded = JsonPayload.decode(bytes); +``` + +## Complete Example + +```typescript +import { + defineSdk, + returnString, + returnInt, + streamString, +} from "@globe/runtime_types"; + +type ModuleState = { + apiUrl: string; + timeout: number; +}; + +const fetchUsers = streamString( + async (state: ModuleState, callbackId: number) => { + try { + const response = await fetch(state.apiUrl + "/users"); + + for await (const chunk of response.body!.values()) { + Dart.stream_value(callbackId, chunk); + } + + Dart.stream_value_end(callbackId); + } catch (error) { + Dart.send_error(callbackId, `Stream failed: ${error.message}`); + } + } +); + +const calculatePrice = returnInt( + (state: ModuleState, quantity: number, price: number, callbackId: number) => { + const total = quantity * price; + Dart.send_value(callbackId, new TextEncoder().encode(total.toString())); + } +); + +export default defineSdk({ + init(apiUrl: string = "https://api.example.com", timeout: number = 5000): ModuleState { + return { apiUrl, timeout }; + }, + functions: { + fetchUsers, + calculatePrice, + }, +}); +``` + +## Next Steps + +Once you've defined your SDK, use the [@globe/dart_source_generator](https://www.npmjs.com/package/@globe/dart_source_generator) to generate Dart source files that can be used in your Flutter/Dart projects. + +## License + +See LICENSE for details. \ No newline at end of file diff --git a/packages/globe_runtime_ts/runtime_types/index.d.ts b/packages/globe_runtime_ts/runtime_types/index.d.ts new file mode 100644 index 0000000..17ca72f --- /dev/null +++ b/packages/globe_runtime_ts/runtime_types/index.d.ts @@ -0,0 +1,357 @@ +declare global { + type DartValue = Uint8Array | undefined; + + interface DartGlobal { + /** + * Sends data back to Dart from JavaScript. + * + * @param callbackId - A unique identifier for the callback. + * @param data - The data to send. + * @returns {boolean} - Returns true if the data was sent successfully. + */ + send_value: (callbackId: CallbackId, data: DartValue) => boolean; + + /** + * Sends an error message back to Dart from JavaScript. + * + * @param callbackId - A unique identifier for the callback. + * @param error - The error message to send. + */ + send_error: (callbackId: CallbackId, error: string) => boolean; + + /** + * Sends data back to Dart from JavaScript. + * + * @param callbackId - A unique identifier for the callback. + * @param data - The data to send. + * @returns {boolean} - Returns true if the data was sent successfully. + */ + stream_value: (callbackId: CallbackId, data: DartValue) => boolean; + + /** + * Sends data back to Dart from JavaScript. + * + * @param callbackId - A unique identifier for the callback. + * @param data - The data to send. + * @returns {boolean} - Returns true if the data was sent successfully. + */ + stream_value_end: (callbackId: CallbackId, data?: DartValue) => boolean; + } + + const Dart: DartGlobal; + + const JsonPayload: { + // Encoding payload using MessagePack + encode(value: unknown): DartValue; + // Decoding payload using MessagePack + decode(value: Uint8Array): any; + }; +} + +/** + * A callback identifier used by the Dart runtime. + */ +export type CallbackId = number; + +/** + * Worker functions must never return a value directly. + * They must always send results using Dart.send_value or Dart.stream_value. + */ +export type WorkerFunctionReturn = void | Promise; + +/** + * Marker types for Dart collection types + */ +export type DartMap = { __dartType: "Map" }; +export type DartList = { __dartType: "List" }; +export type DartSet = { __dartType: "Set" }; + +/** + * Marker type for single-value Dart returns + */ +export type DartReturn = void & { __dartReturnType?: T }; + +/** + * Marker type for streaming Dart returns + */ +export type DartStreamReturn = void & { __dartStreamReturnType?: T }; + +/** + * A worker function receives: + * - state: the object returned from init() + * - args: arguments from Dart (excluding callbackId) + * - callbackId: always the last parameter + * + * T = the type of the value that will be encoded and sent via send_value/stream_value. + * Args = argument types excluding callbackId. + */ +export type WorkerFunction = ( + state: State, + ...argsAndCallback: [...args: Args, callbackId: CallbackId] +) => DartReturn; + +export type StreamWorkerFunction = ( + state: State, + ...argsAndCallback: [...args: Args, callbackId: CallbackId] +) => DartStreamReturn; + +/** + * Define a worker function that sends a single value back to Dart. + * + * @example + * const myFunc = defineFunction()( + * (state: ModuleState, value: number, callbackId: number) => { + * const result = processValue(value); + * Dart.send_value(callbackId, new TextEncoder().encode(result)); + * } + * ); + */ +export function defineFunction( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Define a worker function that streams multiple values back to Dart. + * + * @example + * const myStreamFunc = defineStreamFunction()( + * (state: ModuleState, value: number, callbackId: number) => { + * Dart.stream_value(callbackId, new TextEncoder().encode("chunk1")); + * Dart.stream_value(callbackId, new TextEncoder().encode("chunk2")); + * Dart.stream_value_end(callbackId); + * } + * ); + */ +export function defineStreamFunction( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +// ====================================================== +// Pre-configured Helpers - Single Value Returns +// ====================================================== + +/** + * Helper for functions that return a string to Dart (Dart: String, JS: string). + * @example + * const myFunc = returnString((state, value, callbackId) => { + * Dart.send_value(callbackId, new TextEncoder().encode("result")); + * }); + */ +export function returnString( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return an int to Dart (Dart: int, JS: number). + * @example + * const myFunc = returnInt((state, value, callbackId) => { + * const result = 42; + * Dart.send_value(callbackId, new TextEncoder().encode(result.toString())); + * }); + */ +export function returnInt( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a double to Dart (Dart: double, JS: number). + * @example + * const myFunc = returnDouble((state, value, callbackId) => { + * const result = 3.14; + * Dart.send_value(callbackId, new TextEncoder().encode(result.toString())); + * }); + */ +export function returnDouble( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a number to Dart (Dart: num, JS: number). + * @example + * const myFunc = returnNumber((state, value, callbackId) => { + * Dart.send_value(callbackId, new TextEncoder().encode("42")); + * }); + */ +export function returnNumber( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a boolean to Dart (Dart: bool, JS: boolean). + * @example + * const myFunc = returnBoolean((state, value, callbackId) => { + * Dart.send_value(callbackId, new TextEncoder().encode("true")); + * }); + */ +export function returnBoolean( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a Uint8Array to Dart (Dart: List, JS: Uint8Array). + * @example + * const myFunc = returnUint8Array((state, value, callbackId) => { + * Dart.send_value(callbackId, new Uint8Array([1, 2, 3])); + * }); + */ +export function returnUint8Array( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a Map to Dart (Dart: Map, JS: object). + * @example + * const myFunc = returnMap((state, value, callbackId) => { + * const encoded = JsonPayload.encode({ key: "value" }); + * Dart.send_value(callbackId, encoded!); + * }); + */ +export function returnMap( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a List to Dart (Dart: List, JS: object). + * @example + * const myFunc = returnList((state, value, callbackId) => { + * const encoded = JsonPayload.encode([1, 2, 3]); + * Dart.send_value(callbackId, encoded!); + * }); + */ +export function returnList( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +/** + * Helper for functions that return a Set to Dart (Dart: Set, JS: object). + * @example + * const myFunc = returnSet((state, value, callbackId) => { + * const encoded = JsonPayload.encode([1, 2, 3]); // Sets are encoded as arrays + * Dart.send_value(callbackId, encoded!); + * }); + */ +export function returnSet( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartReturn; + +// ====================================================== +// Pre-configured Helpers - Streaming Returns +// ====================================================== + +/** + * Helper for functions that stream strings to Dart (Dart: Stream, JS: string). + * @example + * const myFunc = streamString((state, count, callbackId) => { + * Dart.stream_value(callbackId, new TextEncoder().encode("chunk1")); + * Dart.stream_value_end(callbackId); + * }); + */ +export function streamString( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream ints to Dart (Dart: Stream, JS: number). + */ +export function streamInt( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream doubles to Dart (Dart: Stream, JS: number). + */ +export function streamDouble( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream numbers to Dart (Dart: Stream, JS: number). + */ +export function streamNumber( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream booleans to Dart (Dart: Stream, JS: boolean). + */ +export function streamBoolean( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream Uint8Array to Dart (Dart: Stream>, JS: Uint8Array). + */ +export function streamUint8Array( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream Maps to Dart (Dart: Stream>, JS: object). + */ +export function streamMap( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream Lists to Dart (Dart: Stream>, JS: object). + */ +export function streamList( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +/** + * Helper for functions that stream Sets to Dart (Dart: Stream>, JS: object). + */ +export function streamSet( + fn: (state: State, ...args: Args) => WorkerFunctionReturn +): (state: State, ...args: Args) => DartStreamReturn; + +export interface SdkDefinition< + InitArgs extends any[], + State, + Fns extends Record +> { + init: (...args: InitArgs) => State; + functions: Fns; +} + +/** + * The resolved SDK type after calling defineSdk(). + */ +export interface Sdk< + InitFn extends (...args: any) => any, + Fns extends Record +> { + init: InitFn; + functions: Fns; +} + +/** + * Typed SDK creator. + * + * @example + * const sdk = defineSdk({ + * init(a: string, b: number) { + * return { a, b }; + * }, + * functions: { + * myFunc: returnString((state: {a: string, b: number}, x: string, callbackId) => { ... }) + * } + * }); + * + * All worker functions MUST return DartReturn | DartStreamReturn. + */ +export function defineSdk< + Def extends { + init?: (...args: any) => any; + functions: Record; + } +>( + def: Def +): Def & + Sdk< + Def["init"] extends (...args: any) => any ? Def["init"] : () => void, + Def["functions"] + >; + +export {}; diff --git a/packages/globe_runtime_ts/runtime_types/index.js b/packages/globe_runtime_ts/runtime_types/index.js new file mode 100644 index 0000000..f6f3d0d --- /dev/null +++ b/packages/globe_runtime_ts/runtime_types/index.js @@ -0,0 +1,271 @@ +/** + * @typedef {number} CallbackId + */ + +/** + * Global Dart interop interface for sending data back to the Dart runtime. + * + * @typedef {Object} DartGlobal + * @property {(callbackId: CallbackId, data: Uint8Array) => boolean} send_value - Sends data back to Dart from JavaScript. + * @property {(callbackId: CallbackId, error: string) => boolean} send_error - Sends an error message back to Dart from JavaScript. + * @property {(callbackId: CallbackId, data: Uint8Array) => boolean} stream_value - Sends data back to Dart from JavaScript. + * @property {(callbackId: CallbackId, data?: Uint8Array) => boolean} stream_value_end - Sends data back to Dart from JavaScript. + */ + +/** + * Global payload encoding/decoding interface using MessagePack format. + * + * @typedef {Object} JsonPayloadGlobal + * @property {(value: unknown) => Uint8Array | undefined} encode - Encoding payload using MessagePack + * @property {(value: Uint8Array) => any} decode - Decoding payload using MessagePack + */ + +/** + * Global Dart interop object for communicating with the Dart runtime. + * @global + * @type {DartGlobal} + */ +globalThis.Dart ??= {}; + +/** + * Global payload encoding/decoding utility using MessagePack. + * @global + * @type {JsonPayloadGlobal} + */ +globalThis.JsonPayload ??= {}; + +/** + * @typedef {void | Promise} WorkerFunctionReturn + */ + +/** + * @typedef {{ __dartType: "Map" }} DartMap + */ + +/** + * @typedef {{ __dartType: "List" }} DartList + */ + +/** + * @typedef {{ __dartType: "Set" }} DartSet + */ + +/** + * @template T + * @typedef {void & { __dartReturnType?: T }} DartReturn + */ + +/** + * @template T + * @typedef {void & { __dartStreamReturnType?: T }} DartStreamReturn + */ + +/** + * Helper function to return a worker function with proper typing. + * + * @returns {(fn: Function) => Function} A function that takes a worker function and returns it with proper typing + */ +const returnFn = () => { + return function (fn) { + return fn; + }; +}; + +/** + * Define a worker function that sends a single value back to Dart. + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const defineFunction = returnFn; + +/** + * Define a worker function that streams multiple values back to Dart. + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const defineStreamFunction = returnFn; + +// ====================================================== +// Pre-configured Helpers - Single Value Returns +// ====================================================== + +/** + * Helper for functions that return a string to Dart (Dart: String, JS: string). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnString = defineFunction(); + +/** + * Helper for functions that return an int to Dart (Dart: int, JS: number). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnInt = defineFunction(); + +/** + * Helper for functions that return a double to Dart (Dart: double, JS: number). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnDouble = defineFunction(); + +/** + * Helper for functions that return a number to Dart (Dart: num, JS: number). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnNumber = defineFunction(); + +/** + * Helper for functions that return a boolean to Dart (Dart: bool, JS: boolean). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnBoolean = defineFunction(); + +/** + * Helper for functions that return a Uint8Array to Dart (Dart: List, JS: Uint8Array). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnUint8Array = defineFunction(); + +/** + * Helper for functions that return a Map to Dart (Dart: Map, JS: object). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnMap = defineFunction(); + +/** + * Helper for functions that return a List to Dart (Dart: List, JS: object). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnList = defineFunction(); + +/** + * Helper for functions that return a Set to Dart (Dart: Set, JS: object). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartReturn} The wrapped worker function + */ +export const returnSet = defineFunction(); + +// ====================================================== +// Pre-configured Helpers - Streaming Returns +// ====================================================== + +/** + * Helper for functions that stream strings to Dart (Dart: Stream, JS: string). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamString = defineStreamFunction(); + +/** + * Helper for functions that stream ints to Dart (Dart: Stream, JS: number). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamInt = defineStreamFunction(); + +/** + * Helper for functions that stream doubles to Dart (Dart: Stream, JS: number). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamDouble = defineStreamFunction(); + +/** + * Helper for functions that stream numbers to Dart (Dart: Stream, JS: number). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamNumber = defineStreamFunction(); + +/** + * Helper for functions that stream booleans to Dart (Dart: Stream, JS: boolean). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamBoolean = defineStreamFunction(); + +/** + * Helper for functions that stream Uint8Array to Dart (Dart: Stream>, JS: Uint8Array). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamUint8Array = defineStreamFunction(); + +/** + * Helper for functions that stream Maps to Dart (Dart: Stream>, JS: object). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamMap = defineStreamFunction(); + +/** + * Helper for functions that stream Lists to Dart (Dart: Stream>, JS: object). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamList = defineStreamFunction(); + +/** + * Helper for functions that stream Sets to Dart (Dart: Stream>, JS: object). + * + * @template State, Args + * @param {(state: State, ...argsAndCallback: [...Args, CallbackId]) => WorkerFunctionReturn} fn - The worker function to wrap + * @returns {(state: State, ...argsAndCallback: [...Args, CallbackId]) => DartStreamReturn} The wrapped worker function + */ +export const streamSet = defineStreamFunction(); + +/** + * Typed SDK creator. + * + * @template InitFn, Fns, State, InitArgs + * @param {Object} def - SDK definition with init and functions + * @param {InitFn} def.init - Initialization function that returns state + * @param {Fns} def.functions - Object containing worker functions + * @returns {{init?: InitFn, functions: Fns}} The SDK definition + */ +export const defineSdk = returnFn(); \ No newline at end of file diff --git a/packages/globe_runtime_ts/package-lock.json b/packages/globe_runtime_ts/runtime_types/package-lock.json similarity index 100% rename from packages/globe_runtime_ts/package-lock.json rename to packages/globe_runtime_ts/runtime_types/package-lock.json diff --git a/packages/globe_runtime_ts/package.json b/packages/globe_runtime_ts/runtime_types/package.json similarity index 87% rename from packages/globe_runtime_ts/package.json rename to packages/globe_runtime_ts/runtime_types/package.json index 6a00714..4bbcdd8 100644 --- a/packages/globe_runtime_ts/package.json +++ b/packages/globe_runtime_ts/runtime_types/package.json @@ -3,6 +3,8 @@ "version": "1.0.3", "description": "Global type declarations for the Dart JS runtime interop", "types": "index.d.ts", + "main": "index.js", + "type": "module", "sideEffects": false, "keywords": [ "dart", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ada58e4..f320064 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,9 @@ settings: catalogs: default: + '@types/node': + specifier: 25.0.3 + version: 25.0.3 fs: specifier: 0.0.1-security version: 0.0.1-security @@ -13,14 +16,58 @@ catalogs: specifier: 0.12.7 version: 0.12.7 tsup: - specifier: 8.0.2 - version: 8.0.2 + specifier: 8.5.1 + version: 8.5.1 typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 5.9.3 + version: 5.9.3 importers: + examples/full_example: + dependencies: + pretty-bytes: + specifier: ^7.1.0 + version: 7.1.0 + pretty-ms: + specifier: ^9.3.0 + version: 9.3.0 + devDependencies: + '@globe/dart_source_generator': + specifier: workspace:* + version: link:../../packages/globe_runtime_ts/dart_source_generator + '@globe/runtime_types': + specifier: workspace:* + version: link:../../packages/globe_runtime_ts/runtime_types + '@types/node': + specifier: 'catalog:' + version: 25.0.3 + typescript: + specifier: 'catalog:' + version: 5.9.3 + + examples/js_to_dart_docs: + dependencies: + pretty-bytes: + specifier: ^7.1.0 + version: 7.1.0 + pretty-ms: + specifier: ^9.3.0 + version: 9.3.0 + devDependencies: + '@globe/dart_source_generator': + specifier: workspace:* + version: link:../../packages/globe_runtime_ts/dart_source_generator + '@globe/runtime_types': + specifier: workspace:* + version: link:../../packages/globe_runtime_ts/runtime_types + '@types/node': + specifier: 'catalog:' + version: 25.0.3 + typescript: + specifier: 'catalog:' + version: 5.9.3 + examples/mjml: dependencies: mjml-browser: @@ -29,7 +76,7 @@ importers: devDependencies: '@globe/runtime_types': specifier: workspace:* - version: link:../../packages/globe_runtime_ts + version: link:../../packages/globe_runtime_ts/runtime_types '@types/mjml-browser': specifier: ^4.15.0 version: 4.15.0 @@ -41,313 +88,503 @@ importers: version: 0.12.7 tsup: specifier: 'catalog:' - version: 8.0.2(typescript@5.8.3) + version: 8.5.1(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.1) typescript: specifier: 'catalog:' - version: 5.8.3 + version: 5.9.3 examples/pretty_node: dependencies: pretty-bytes: - specifier: ^7.0.0 + specifier: ^7.1.0 version: 7.1.0 pretty-ms: - specifier: ^9.2.0 + specifier: ^9.3.0 version: 9.3.0 devDependencies: + '@globe/dart_source_generator': + specifier: workspace:* + version: link:../../packages/globe_runtime_ts/dart_source_generator '@globe/runtime_types': specifier: workspace:* - version: link:../../packages/globe_runtime_ts - fs: + version: link:../../packages/globe_runtime_ts/runtime_types + '@types/node': specifier: 'catalog:' - version: 0.0.1-security - path: - specifier: 'catalog:' - version: 0.12.7 + version: 25.0.3 tsup: specifier: 'catalog:' - version: 8.0.2(typescript@5.8.3) + version: 8.5.1(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.1) typescript: specifier: 'catalog:' - version: 5.8.3 + version: 5.9.3 - packages/globe_runtime_ts: {} + packages/globe_runtime_ts/dart_source_generator: + dependencies: + glob: + specifier: ^13.0.0 + version: 13.0.0 + text-case: + specifier: ^1.2.9 + version: 1.2.9 + tsdown: + specifier: ^0.18.2 + version: 0.18.2(typescript@5.9.3) + tslog: + specifier: ^4.10.2 + version: 4.10.2 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + devDependencies: + '@globe/runtime_types': + specifier: workspace:* + version: link:../runtime_types + '@types/node': + specifier: ^25.0.3 + version: 25.0.3 + '@vitest/coverage-v8': + specifier: ^4.0.16 + version: 4.0.16(vitest@4.0.16(@types/node@25.0.3)(yaml@2.8.1)) + vitest: + specifier: ^4.0.16 + version: 4.0.16(@types/node@25.0.3)(yaml@2.8.1) + + packages/globe_runtime_ts/runtime_types: {} packages: - '@esbuild/aix-ppc64@0.19.12': - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} - engines: {node: '>=12'} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@emnapi/core@1.7.1': + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.19.12': - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} - engines: {node: '>=12'} + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.19.12': - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.19.12': - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.19.12': - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.19.12': - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.19.12': - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.19.12': - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.19.12': - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.19.12': - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.19.12': - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.19.12': - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.19.12': - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.19.12': - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.19.12': - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.19.12': - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.19.12': - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-x64@0.19.12': - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} - engines: {node: '>=12'} + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-x64@0.19.12': - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} - engines: {node: '>=12'} + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.19.12': - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} - engines: {node: '>=12'} + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.19.12': - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.19.12': - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.19.12': - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} cpu: [x64] os: [win32] + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@napi-rs/wasm-runtime@1.1.0': + resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@oxc-project/types@0.103.0': + resolution: {integrity: sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@rollup/rollup-android-arm-eabi@4.34.6': - resolution: {integrity: sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==} + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + + '@rolldown/binding-android-arm64@1.0.0-beta.55': + resolution: {integrity: sha512-5cPpHdO+zp+klznZnIHRO1bMHDq5hS9cqXodEKAaa/dQTPDjnE91OwAsy3o1gT2x4QaY8NzdBXAvutYdaw0WeA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.55': + resolution: {integrity: sha512-l0887CGU2SXZr0UJmeEcXSvtDCOhDTTYXuoWbhrEJ58YQhQk24EVhDhHMTyjJb1PBRniUgNc1G0T51eF8z+TWw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.55': + resolution: {integrity: sha512-d7qP2AVYzN0tYIP4vJ7nmr26xvmlwdkLD/jWIc9Z9dqh5y0UGPigO3m5eHoHq9BNazmwdD9WzDHbQZyXFZjgtA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.55': + resolution: {integrity: sha512-j311E4NOB0VMmXHoDDZhrWidUf7L/Sa6bu/+i2cskvHKU40zcUNPSYeD2YiO2MX+hhDFa5bJwhliYfs+bTrSZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.55': + resolution: {integrity: sha512-lAsaYWhfNTW2A/9O7zCpb5eIJBrFeNEatOS/DDOZ5V/95NHy50g4b/5ViCqchfyFqRb7MKUR18/+xWkIcDkeIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.55': + resolution: {integrity: sha512-2x6ffiVLZrQv7Xii9+JdtyT1U3bQhKj59K3eRnYlrXsKyjkjfmiDUVx2n+zSyijisUqD62fcegmx2oLLfeTkCA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.55': + resolution: {integrity: sha512-QbNncvqAXziya5wleI+OJvmceEE15vE4yn4qfbI/hwT/+8ZcqxyfRZOOh62KjisXxp4D0h3JZspycXYejxAU3w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.55': + resolution: {integrity: sha512-YZCTZZM+rujxwVc6A+QZaNMJXVtmabmFYLG2VGQTKaBfYGvBKUgtbMEttnp/oZ88BMi2DzadBVhOmfQV8SuHhw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.55': + resolution: {integrity: sha512-28q9OQ/DDpFh2keS4BVAlc3N65/wiqKbk5K1pgLdu/uWbKa8hgUJofhXxqO+a+Ya2HVTUuYHneWsI2u+eu3N5Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.55': + resolution: {integrity: sha512-LiCA4BjCnm49B+j1lFzUtlC+4ZphBv0d0g5VqrEJua/uyv9Ey1v9tiaMql1C8c0TVSNDUmrkfHQ71vuQC7YfpQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.55': + resolution: {integrity: sha512-nZ76tY7T0Oe8vamz5Cv5CBJvrqeQxwj1WaJ2GxX8Msqs0zsQMMcvoyxOf0glnJlxxgKjtoBxAOxaAU8ERbW6Tg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.55': + resolution: {integrity: sha512-TFVVfLfhL1G+pWspYAgPK/FSqjiBtRKYX9hixfs508QVEZPQlubYAepHPA7kEa6lZXYj5ntzF87KC6RNhxo+ew==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.55': + resolution: {integrity: sha512-j1WBlk0p+ISgLzMIgl0xHp1aBGXenoK2+qWYc/wil2Vse7kVOdFq9aeQ8ahK6/oxX2teQ5+eDvgjdywqTL+daA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.55': + resolution: {integrity: sha512-vajw/B3qoi7aYnnD4BQ4VoCcXQWnF0roSwE2iynbNxgW4l9mFwtLmLmUhpDdcTBfKyZm1p/T0D13qG94XBLohA==} + + '@rollup/rollup-android-arm-eabi@4.53.5': + resolution: {integrity: sha512-iDGS/h7D8t7tvZ1t6+WPK04KD0MwzLZrG0se1hzBjSi5fyxlsiggoJHwh18PCFNn7tG43OWb6pdZ6Y+rMlmyNQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.34.6': - resolution: {integrity: sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==} + '@rollup/rollup-android-arm64@4.53.5': + resolution: {integrity: sha512-wrSAViWvZHBMMlWk6EJhvg8/rjxzyEhEdgfMMjREHEq11EtJ6IP6yfcCH57YAEca2Oe3FNCE9DSTgU70EIGmVw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.34.6': - resolution: {integrity: sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==} + '@rollup/rollup-darwin-arm64@4.53.5': + resolution: {integrity: sha512-S87zZPBmRO6u1YXQLwpveZm4JfPpAa6oHBX7/ghSiGH3rz/KDgAu1rKdGutV+WUI6tKDMbaBJomhnT30Y2t4VQ==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.34.6': - resolution: {integrity: sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==} + '@rollup/rollup-darwin-x64@4.53.5': + resolution: {integrity: sha512-YTbnsAaHo6VrAczISxgpTva8EkfQus0VPEVJCEaboHtZRIb6h6j0BNxRBOwnDciFTZLDPW5r+ZBmhL/+YpTZgA==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.34.6': - resolution: {integrity: sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==} + '@rollup/rollup-freebsd-arm64@4.53.5': + resolution: {integrity: sha512-1T8eY2J8rKJWzaznV7zedfdhD1BqVs1iqILhmHDq/bqCUZsrMt+j8VCTHhP0vdfbHK3e1IQ7VYx3jlKqwlf+vw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.34.6': - resolution: {integrity: sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==} + '@rollup/rollup-freebsd-x64@4.53.5': + resolution: {integrity: sha512-sHTiuXyBJApxRn+VFMaw1U+Qsz4kcNlxQ742snICYPrY+DDL8/ZbaC4DVIB7vgZmp3jiDaKA0WpBdP0aqPJoBQ==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.34.6': - resolution: {integrity: sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.5': + resolution: {integrity: sha512-dV3T9MyAf0w8zPVLVBptVlzaXxka6xg1f16VAQmjg+4KMSTWDvhimI/Y6mp8oHwNrmnmVl9XxJ/w/mO4uIQONA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.34.6': - resolution: {integrity: sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==} + '@rollup/rollup-linux-arm-musleabihf@4.53.5': + resolution: {integrity: sha512-wIGYC1x/hyjP+KAu9+ewDI+fi5XSNiUi9Bvg6KGAh2TsNMA3tSEs+Sh6jJ/r4BV/bx/CyWu2ue9kDnIdRyafcQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.34.6': - resolution: {integrity: sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==} + '@rollup/rollup-linux-arm64-gnu@4.53.5': + resolution: {integrity: sha512-Y+qVA0D9d0y2FRNiG9oM3Hut/DgODZbU9I8pLLPwAsU0tUKZ49cyV1tzmB/qRbSzGvY8lpgGkJuMyuhH7Ma+Vg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.34.6': - resolution: {integrity: sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==} + '@rollup/rollup-linux-arm64-musl@4.53.5': + resolution: {integrity: sha512-juaC4bEgJsyFVfqhtGLz8mbopaWD+WeSOYr5E16y+1of6KQjc0BpwZLuxkClqY1i8sco+MdyoXPNiCkQou09+g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.34.6': - resolution: {integrity: sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==} + '@rollup/rollup-linux-loong64-gnu@4.53.5': + resolution: {integrity: sha512-rIEC0hZ17A42iXtHX+EPJVL/CakHo+tT7W0pbzdAGuWOt2jxDFh7A/lRhsNHBcqL4T36+UiAgwO8pbmn3dE8wA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.34.6': - resolution: {integrity: sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==} + '@rollup/rollup-linux-ppc64-gnu@4.53.5': + resolution: {integrity: sha512-T7l409NhUE552RcAOcmJHj3xyZ2h7vMWzcwQI0hvn5tqHh3oSoclf9WgTl+0QqffWFG8MEVZZP1/OBglKZx52Q==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.34.6': - resolution: {integrity: sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==} + '@rollup/rollup-linux-riscv64-gnu@4.53.5': + resolution: {integrity: sha512-7OK5/GhxbnrMcxIFoYfhV/TkknarkYC1hqUw1wU2xUN3TVRLNT5FmBv4KkheSG2xZ6IEbRAhTooTV2+R5Tk0lQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.53.5': + resolution: {integrity: sha512-GwuDBE/PsXaTa76lO5eLJTyr2k8QkPipAyOrs4V/KJufHCZBJ495VCGJol35grx9xryk4V+2zd3Ri+3v7NPh+w==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.34.6': - resolution: {integrity: sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==} + '@rollup/rollup-linux-s390x-gnu@4.53.5': + resolution: {integrity: sha512-IAE1Ziyr1qNfnmiQLHBURAD+eh/zH1pIeJjeShleII7Vj8kyEm2PF77o+lf3WTHDpNJcu4IXJxNO0Zluro8bOw==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.34.6': - resolution: {integrity: sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==} + '@rollup/rollup-linux-x64-gnu@4.53.5': + resolution: {integrity: sha512-Pg6E+oP7GvZ4XwgRJBuSXZjcqpIW3yCBhK4BcsANvb47qMvAbCjR6E+1a/U2WXz1JJxp9/4Dno3/iSJLcm5auw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.34.6': - resolution: {integrity: sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==} + '@rollup/rollup-linux-x64-musl@4.53.5': + resolution: {integrity: sha512-txGtluxDKTxaMDzUduGP0wdfng24y1rygUMnmlUJ88fzCCULCLn7oE5kb2+tRB+MWq1QDZT6ObT5RrR8HFRKqg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.34.6': - resolution: {integrity: sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==} + '@rollup/rollup-openharmony-arm64@4.53.5': + resolution: {integrity: sha512-3DFiLPnTxiOQV993fMc+KO8zXHTcIjgaInrqlG8zDp1TlhYl6WgrOHuJkJQ6M8zHEcntSJsUp1XFZSY8C1DYbg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.53.5': + resolution: {integrity: sha512-nggc/wPpNTgjGg75hu+Q/3i32R00Lq1B6N1DO7MCU340MRKL3WZJMjA9U4K4gzy3dkZPXm9E1Nc81FItBVGRlA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.34.6': - resolution: {integrity: sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==} + '@rollup/rollup-win32-ia32-msvc@4.53.5': + resolution: {integrity: sha512-U/54pTbdQpPLBdEzCT6NBCFAfSZMvmjr0twhnD9f4EIvlm9wy3jjQ38yQj1AGznrNO65EWQMgm/QUjuIVrYF9w==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.34.6': - resolution: {integrity: sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==} + '@rollup/rollup-win32-x64-gnu@4.53.5': + resolution: {integrity: sha512-2NqKgZSuLH9SXBBV2dWNRCZmocgSOx8OJSdpRaEcRlIfX8YrKxUT6z0F1NpvDVhOsl190UFTRh2F2WDWWCYp3A==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.53.5': + resolution: {integrity: sha512-JRpZUhCfhZ4keB5v0fe02gQJy05GqboPOaxvjugW04RLSYYoB/9t2lx2u/tMs/Na/1NXfY8QYjgRljRpN+MjTQ==} cpu: [x64] os: [win32] - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/mjml-browser@4.15.0': resolution: {integrity: sha512-WNmr7LB4XfSM4pe+ES3zCcF4NY3hfPQxLNPn8v3GgNYc3u2rJbiQ56Ahswn/WF9kpO+M5jKd2jlq8u2ZAV0g6A==} @@ -355,6 +592,52 @@ packages: '@types/mjml-core@4.15.2': resolution: {integrity: sha512-Q7SxFXgoX979HP57DEVsRI50TV8x1V4lfCA4Up9AvfINDM5oD/X9ARgfoyX1qS987JCnDLv85JjkqAjt3hZSiQ==} + '@types/node@25.0.3': + resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==} + + '@vitest/coverage-v8@4.0.16': + resolution: {integrity: sha512-2rNdjEIsPRzsdu6/9Eq0AYAzYdpP6Bx9cje9tL3FE5XzXRQF1fNU9pe/1yE8fCrS0HD+fBtt6gLPh6LI57tX7A==} + peerDependencies: + '@vitest/browser': 4.0.16 + vitest: 4.0.16 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@4.0.16': + resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==} + + '@vitest/mocker@4.0.16': + resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.0.16': + resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==} + + '@vitest/runner@4.0.16': + resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==} + + '@vitest/snapshot@4.0.16': + resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==} + + '@vitest/spy@4.0.16': + resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==} + + '@vitest/utils@4.0.16': + resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -371,44 +654,50 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} + ast-kit@2.2.0: + resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==} + engines: {node: '>=20.19.0'} + + ast-v8-to-istanbul@0.3.9: + resolution: {integrity: sha512-dSC6tJeOJxbZrPzPbv5mMd6CMiQ1ugaVXXPRad2fXUSsy1kstFn9XQWemV9VW7Y7kpxgQ/4WMoZfwdH8XSU48w==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} + birpc@4.0.0: + resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - bundle-require@4.2.1: - resolution: {integrity: sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==} + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: - esbuild: '>=0.17' + esbuild: '>=0.18' cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chai@6.2.1: + resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} + engines: {node: '>=18'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -421,6 +710,13 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -434,9 +730,17 @@ packages: supports-color: optional: true - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + dts-resolver@2.1.3: + resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} + engines: {node: '>=20.19.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -447,25 +751,36 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} hasBin: true - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} foreground-child@3.3.0: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} @@ -479,60 +794,57 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + get-tsconfig@4.13.0: + resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + glob@13.0.0: + resolution: {integrity: sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==} + engines: {node: 20 || >=22} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hookable@6.0.1: + resolution: {integrity: sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw==} - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} + import-without-cache@0.2.5: + resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} + engines: {node: '>=20.19.0'} inherits@2.0.3: resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -540,6 +852,14 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + lilconfig@3.1.3: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} @@ -551,26 +871,26 @@ packages: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lodash.sortby@4.7.0: - resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + lru-cache@11.2.4: + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + engines: {node: 20 || >=22} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + magicast@0.5.1: + resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==} - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + minimatch@10.1.1: + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} @@ -583,27 +903,26 @@ packages: mjml-browser@4.17.1: resolution: {integrity: sha512-8JYPN3zv5KgkTmvdkKn5IDmSaG2ygWuz1wbVK29m1gvnrX6Y0kwCQdUMW9CCP75apseAqCYaEo2mY0TvpOX4dA==} + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -620,33 +939,52 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + path-scurry@2.0.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} path@0.12.7: resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} - postcss-load-config@4.0.2: - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} peerDependencies: + jiti: '>=1.21.0' postcss: '>=8.0.9' - ts-node: '>=9.0.0' + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: + jiti: + optional: true postcss: optional: true - ts-node: + tsx: + optional: true + yaml: optional: true + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + pretty-bytes@7.1.0: resolution: {integrity: sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw==} engines: {node: '>=20'} @@ -659,32 +997,53 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - rollup@4.34.6: - resolution: {integrity: sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==} + rolldown-plugin-dts@0.19.1: + resolution: {integrity: sha512-6z501zDTGq6ZrIEdk57qNUwq7kBRGzv3I3SAN2HMJ2KFYjHLnAuPYOmvfiwdxbRZMJ0iMdkV9rYdC3GjurT2cg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@ts-macro/tsc': ^0.3.6 + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-beta.55 + typescript: ^5.0.0 + vue-tsc: ~3.1.0 + peerDependenciesMeta: + '@ts-macro/tsc': + optional: true + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-beta.55: + resolution: {integrity: sha512-r8Ws43aYCnfO07ao0SvQRz4TBAtZJjGWNvScRBOHuiNHvjfECOJBIqJv0nUkL1GYcltjvvHswRilDF1ocsC0+g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.53.5: + resolution: {integrity: sha512-iTNAbFSlRpcHeeWu73ywU/8KuU/LZmNCSxp6fjQkJBD3ivUb8tpDrXhIxEzA05HlYMEwmtaUnb3RP+YNv162OQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} @@ -694,21 +1053,26 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} - source-map@0.8.0-beta.0: - resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} - engines: {node: '>= 8'} - deprecated: The work that was done in this beta branch won't be included in future versions + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -726,15 +1090,78 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} hasBin: true + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + text-camel-case@1.2.9: + resolution: {integrity: sha512-wKYs9SgRxYizJE1mneR7BbLNlGw2IYzJAS8XwkWIry0CTbO1gvvPkFsx5Z1/hr+VqUaBqx9q3yKd30HpZLdMsQ==} + + text-capital-case@1.2.9: + resolution: {integrity: sha512-X5zV8U8pxtq2xS2t46lgAWqZdDbgWMKq03MQSNwY2CJdQCsdTNh144E2Q/q9wBxWzSBUXn+jRc9kF+Gs8/pGhA==} + + text-case@1.2.9: + resolution: {integrity: sha512-zZVdA8rMcjx9zhekdUuOPZShc25UTV7W8/ddKbgbPtfCEvIiToPtWiSd2lXLSuiGMovNhJ4+Tw49xll9o9ts+Q==} + + text-constant-case@1.2.9: + resolution: {integrity: sha512-Vosm6nC7Gag+JFakJHwqS9AXRNgl07j5KZ7srU9cYuKRzYwrxzeJ4RpEogRBNHw7CfmOm0j5FGEznblWtu7pIw==} + + text-dot-case@1.2.9: + resolution: {integrity: sha512-N83hsnvGdSO9q9AfNSB9Cy1LFDNN2MCx53LcxtaPoDWPUTk47fv0JlvIY1tgY0wyzCiThF03kVj3jworvAOScA==} + + text-header-case@1.2.9: + resolution: {integrity: sha512-TqryEKcYisQAfWLbtT3xPnZlMZ/mySO1uS+LUg+B0eNuqgETrSzVpXIUj5E6Zf/EyJHgpZf4VndbAXtOMJuT4w==} + + text-is-lower-case@1.2.9: + resolution: {integrity: sha512-cEurrWSnYVYqL8FSwl5cK4mdfqF7qNDCcKJgXI3NnfTesiB8umxAhdlQoErrRYI1xEvYr2WN0MI333EehUhQjg==} + + text-is-upper-case@1.2.9: + resolution: {integrity: sha512-HxsWr3VCsXXiLlhD0c+Ey+mS2lOTCiSJbkepjaXNHl2bp33KiscQaiG0qLwQmmpZQm4SJCg2s9FkndxS0RNDLQ==} + + text-kebab-case@1.2.9: + resolution: {integrity: sha512-nOUyNR5Ej2B9D/wyyXfwUEv26+pQuOb1pEX+ojE37mCIWo8QeOxw5y6nxuqDmG7NrEPzbO6265UMV+EICH13Cw==} + + text-lower-case-first@1.2.9: + resolution: {integrity: sha512-iiphHTV7PVH0MljrEQUA9iBE7jfDpXoi4RQju3WzZU3BRVbS6540cNZgxR19hWa0z6z/7cJTH0Ls9LPBaiUfKg==} + + text-lower-case@1.2.9: + resolution: {integrity: sha512-53AOnDrhPpiAUQkgY1SHleKUXp/u7GsqRX13NcCREZscmtjLLJ099uxMRjkK7q2KwHkFYVPl9ytkQlTkTQLS0w==} + + text-no-case@1.2.9: + resolution: {integrity: sha512-IcCt328KaapimSrytP4ThfC8URmHZb2DgOqCL9BYvGjpxY2lDiqCkIQk9sClZtwcELs2gTnq83a7jNc573FTLA==} + + text-param-case@1.2.9: + resolution: {integrity: sha512-nR/Ju9amY3aQS1en2CUCgqN/ZiZIVdDyjlJ3xX5J92ChBevGuA4o9K10fh3JGMkbzK97Vcb+bWQJ4Q+Svz+GyQ==} + + text-pascal-case@1.2.9: + resolution: {integrity: sha512-o6ZxMGjWDTUW54pcghpXes+C2PqbYRMdU5mHrIhueb6z6nq1NueiIOeCUdrSjN/3wXfhCmnFjK7/d9aRGZNqSg==} + + text-path-case@1.2.9: + resolution: {integrity: sha512-s8cJ6r5TkJp5ticXMgtxd7f12odEN4d1CfX5u4aoz6jcUtBR2lDqzIhVimkqWFMJ4UKPSrmilUha8Xc2BPi+ow==} + + text-sentence-case@1.2.9: + resolution: {integrity: sha512-/G/Yi5kZfUa1edFRV4O3lGZAkbDZTFvlwW8CYfH7szkEGe2k2MYEYbOyAkGRVQEGV6V6JiuUAaP3VS9c1tB6nQ==} + + text-snake-case@1.2.9: + resolution: {integrity: sha512-+ZrqK19ynF/TLQZ7ynqVrL2Dy04uu9syYZwsm8PhzUdsY3XrwPy6QiRqhIEFqhyWbShPcfyfmheer5UEQqFxlw==} + + text-swap-case@1.2.9: + resolution: {integrity: sha512-g5fp12ldktYKK9wdHRMvvtSCQrZYNv/D+ZGLumDsvAY4q9T5bCMO2IWMkIP1F5gVQrysdHH6Xv877P/pjUq1iw==} + + text-title-case@1.2.9: + resolution: {integrity: sha512-RAtC9cdmPp41ns5/HXZBsaQg71BsHT7uZpj2ojTtuFa8o2dNuRYYOrSmy5YdLRIAJQ6WK5hQVpV3jHuq7a+4Tw==} + + text-upper-case-first@1.2.9: + resolution: {integrity: sha512-wEDD1B6XqJmEV+xEnBJd+2sBCHZ+7fvA/8Rv/o8+dAsp05YWjYP/kjB8sPH6zqzW0s6jtehIg4IlcKjcYxk2CQ==} + + text-upper-case@1.2.9: + resolution: {integrity: sha512-K/0DNT7a4z8eah2spARtoJllTZyrNTo6Uc0ujhN/96Ir9uJ/slpahfs13y46H9osL3daaLl3O7iXOkW4xtX6bg==} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -742,12 +1169,23 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} - tr46@1.0.1: - resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} @@ -756,44 +1194,168 @@ packages: ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - tsup@8.0.2: - resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} - engines: {node: '>=18'} + tsdown@0.18.2: + resolution: {integrity: sha512-2o6p/9WjcQrgKnz5/VppOstsqXdTER6G6gPe5yhuP57AueIr2y/NQFKdFPHuqMqZpxRLVjm7MP/dXWG7EJpehg==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@vitejs/devtools': '*' + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@vitejs/devtools': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tslog@4.10.2: + resolution: {integrity: sha512-XuELoRpMR+sq8fuWwX7P0bcj+PRNiicOKDEb3fGNURhxWVyykCi9BNq7c4uVz7h7P0sj8qgBsr5SWS6yBClq3g==} + engines: {node: '>=16'} + + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + + unconfig-core@7.4.2: + resolution: {integrity: sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unrun@0.2.20: + resolution: {integrity: sha512-YhobStTk93HYRN/4iBs3q3/sd7knvju1XrzwwrVVfRujyTG1K88hGONIxCoJN0PWBuO+BX7fFiHH0sVDfE3MWw==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + vite@7.3.0: + resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.0.16: + resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: - '@microsoft/api-extractor': ^7.36.0 - '@swc/core': ^1 - postcss: ^8.4.12 - typescript: '>=4.5.0' + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.16 + '@vitest/browser-preview': 4.0.16 + '@vitest/browser-webdriverio': 4.0.16 + '@vitest/ui': 4.0.16 + happy-dom: '*' + jsdom: '*' peerDependenciesMeta: - '@microsoft/api-extractor': + '@edge-runtime/vm': optional: true - '@swc/core': + '@opentelemetry/api': optional: true - postcss: + '@types/node': optional: true - typescript: + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: optional: true - - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} - engines: {node: '>=14.17'} - hasBin: true - - util@0.10.4: - resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} - - webidl-conversions@4.0.2: - resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - - whatwg-url@7.1.0: - resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -809,75 +1371,129 @@ packages: snapshots: - '@esbuild/aix-ppc64@0.19.12': + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bcoe/v8-coverage@1.0.2': {} + + '@emnapi/core@1.7.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.7.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.27.2': + optional: true + + '@esbuild/android-arm64@0.27.2': + optional: true + + '@esbuild/android-arm@0.27.2': + optional: true + + '@esbuild/android-x64@0.27.2': optional: true - '@esbuild/android-arm64@0.19.12': + '@esbuild/darwin-arm64@0.27.2': optional: true - '@esbuild/android-arm@0.19.12': + '@esbuild/darwin-x64@0.27.2': optional: true - '@esbuild/android-x64@0.19.12': + '@esbuild/freebsd-arm64@0.27.2': optional: true - '@esbuild/darwin-arm64@0.19.12': + '@esbuild/freebsd-x64@0.27.2': optional: true - '@esbuild/darwin-x64@0.19.12': + '@esbuild/linux-arm64@0.27.2': optional: true - '@esbuild/freebsd-arm64@0.19.12': + '@esbuild/linux-arm@0.27.2': optional: true - '@esbuild/freebsd-x64@0.19.12': + '@esbuild/linux-ia32@0.27.2': optional: true - '@esbuild/linux-arm64@0.19.12': + '@esbuild/linux-loong64@0.27.2': optional: true - '@esbuild/linux-arm@0.19.12': + '@esbuild/linux-mips64el@0.27.2': optional: true - '@esbuild/linux-ia32@0.19.12': + '@esbuild/linux-ppc64@0.27.2': optional: true - '@esbuild/linux-loong64@0.19.12': + '@esbuild/linux-riscv64@0.27.2': optional: true - '@esbuild/linux-mips64el@0.19.12': + '@esbuild/linux-s390x@0.27.2': optional: true - '@esbuild/linux-ppc64@0.19.12': + '@esbuild/linux-x64@0.27.2': optional: true - '@esbuild/linux-riscv64@0.19.12': + '@esbuild/netbsd-arm64@0.27.2': optional: true - '@esbuild/linux-s390x@0.19.12': + '@esbuild/netbsd-x64@0.27.2': optional: true - '@esbuild/linux-x64@0.19.12': + '@esbuild/openbsd-arm64@0.27.2': optional: true - '@esbuild/netbsd-x64@0.19.12': + '@esbuild/openbsd-x64@0.27.2': optional: true - '@esbuild/openbsd-x64@0.19.12': + '@esbuild/openharmony-arm64@0.27.2': optional: true - '@esbuild/sunos-x64@0.19.12': + '@esbuild/sunos-x64@0.27.2': optional: true - '@esbuild/win32-arm64@0.19.12': + '@esbuild/win32-arm64@0.27.2': optional: true - '@esbuild/win32-ia32@0.19.12': + '@esbuild/win32-ia32@0.27.2': optional: true - '@esbuild/win32-x64@0.19.12': + '@esbuild/win32-x64@0.27.2': optional: true + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -887,96 +1503,160 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@jridgewell/gen-mapping@0.3.8': + '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} + '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': + '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 - '@nodelib/fs.scandir@2.1.5': + '@napi-rs/wasm-runtime@1.1.0': dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true - '@nodelib/fs.stat@2.0.5': {} + '@oxc-project/types@0.103.0': {} - '@nodelib/fs.walk@1.2.8': + '@pkgjs/parseargs@0.11.0': + optional: true + + '@quansync/fs@1.0.0': dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 + quansync: 1.0.0 - '@pkgjs/parseargs@0.11.0': + '@rolldown/binding-android-arm64@1.0.0-beta.55': optional: true - '@rollup/rollup-android-arm-eabi@4.34.6': + '@rolldown/binding-darwin-arm64@1.0.0-beta.55': optional: true - '@rollup/rollup-android-arm64@4.34.6': + '@rolldown/binding-darwin-x64@1.0.0-beta.55': optional: true - '@rollup/rollup-darwin-arm64@4.34.6': + '@rolldown/binding-freebsd-x64@1.0.0-beta.55': optional: true - '@rollup/rollup-darwin-x64@4.34.6': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.55': optional: true - '@rollup/rollup-freebsd-arm64@4.34.6': + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.55': optional: true - '@rollup/rollup-freebsd-x64@4.34.6': + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.55': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.34.6': + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.55': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.34.6': + '@rolldown/binding-linux-x64-musl@1.0.0-beta.55': optional: true - '@rollup/rollup-linux-arm64-gnu@4.34.6': + '@rolldown/binding-openharmony-arm64@1.0.0-beta.55': optional: true - '@rollup/rollup-linux-arm64-musl@4.34.6': + '@rolldown/binding-wasm32-wasi@1.0.0-beta.55': + dependencies: + '@napi-rs/wasm-runtime': 1.1.0 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.55': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.55': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.55': {} + + '@rollup/rollup-android-arm-eabi@4.53.5': + optional: true + + '@rollup/rollup-android-arm64@4.53.5': + optional: true + + '@rollup/rollup-darwin-arm64@4.53.5': + optional: true + + '@rollup/rollup-darwin-x64@4.53.5': + optional: true + + '@rollup/rollup-freebsd-arm64@4.53.5': + optional: true + + '@rollup/rollup-freebsd-x64@4.53.5': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.53.5': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.53.5': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.53.5': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.53.5': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.53.5': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.53.5': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.53.5': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.34.6': + '@rollup/rollup-linux-riscv64-musl@4.53.5': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.34.6': + '@rollup/rollup-linux-s390x-gnu@4.53.5': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.34.6': + '@rollup/rollup-linux-x64-gnu@4.53.5': optional: true - '@rollup/rollup-linux-s390x-gnu@4.34.6': + '@rollup/rollup-linux-x64-musl@4.53.5': optional: true - '@rollup/rollup-linux-x64-gnu@4.34.6': + '@rollup/rollup-openharmony-arm64@4.53.5': optional: true - '@rollup/rollup-linux-x64-musl@4.34.6': + '@rollup/rollup-win32-arm64-msvc@4.53.5': optional: true - '@rollup/rollup-win32-arm64-msvc@4.34.6': + '@rollup/rollup-win32-ia32-msvc@4.53.5': optional: true - '@rollup/rollup-win32-ia32-msvc@4.34.6': + '@rollup/rollup-win32-x64-gnu@4.53.5': optional: true - '@rollup/rollup-win32-x64-msvc@4.34.6': + '@rollup/rollup-win32-x64-msvc@4.53.5': optional: true - '@types/estree@1.0.6': {} + '@standard-schema/spec@1.1.0': {} + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} '@types/mjml-browser@4.15.0': dependencies: @@ -984,6 +1664,68 @@ snapshots: '@types/mjml-core@4.15.2': {} + '@types/node@25.0.3': + dependencies: + undici-types: 7.16.0 + + '@vitest/coverage-v8@4.0.16(vitest@4.0.16(@types/node@25.0.3)(yaml@2.8.1))': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.0.16 + ast-v8-to-istanbul: 0.3.9 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magicast: 0.5.1 + obug: 2.1.1 + std-env: 3.10.0 + tinyrainbow: 3.0.3 + vitest: 4.0.16(@types/node@25.0.3)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@4.0.16': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + chai: 6.2.1 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.16(vite@7.3.0(@types/node@25.0.3)(yaml@2.8.1))': + dependencies: + '@vitest/spy': 4.0.16 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.0(@types/node@25.0.3)(yaml@2.8.1) + + '@vitest/pretty-format@4.0.16': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.16': + dependencies: + '@vitest/utils': 4.0.16 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.0.16': {} + + '@vitest/utils@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + tinyrainbow: 3.0.3 + + acorn@8.15.0: {} + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -994,45 +1736,43 @@ snapshots: ansi-styles@6.2.1: {} + ansis@4.2.0: {} + any-promise@1.3.0: {} - anymatch@3.1.3: + assertion-error@2.0.1: {} + + ast-kit@2.2.0: dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + '@babel/parser': 7.28.5 + pathe: 2.0.3 - array-union@2.1.0: {} + ast-v8-to-istanbul@0.3.9: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 9.0.1 balanced-match@1.0.2: {} - binary-extensions@2.3.0: {} + birpc@4.0.0: {} brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - bundle-require@4.2.1(esbuild@0.19.12): + bundle-require@5.1.0(esbuild@0.27.2): dependencies: - esbuild: 0.19.12 + esbuild: 0.27.2 load-tsconfig: 0.2.5 cac@6.7.14: {} - chokidar@3.6.0: + chai@6.2.1: {} + + chokidar@4.0.3: dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 + readdirp: 4.1.2 color-convert@2.0.1: dependencies: @@ -1042,6 +1782,10 @@ snapshots: commander@4.1.1: {} + confbox@0.1.8: {} + + consola@3.4.2: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -1052,9 +1796,9 @@ snapshots: dependencies: ms: 2.1.3 - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 + defu@6.1.4: {} + + dts-resolver@2.1.3: {} eastasianwidth@0.2.0: {} @@ -1062,59 +1806,54 @@ snapshots: emoji-regex@9.2.2: {} - esbuild@0.19.12: + empathic@2.0.0: {} + + es-module-lexer@1.7.0: {} + + esbuild@0.27.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - - execa@5.1.1: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + + estree-walker@3.0.3: dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 + '@types/estree': 1.0.8 - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 + expect-type@1.3.0: {} - fastq@1.19.1: - dependencies: - reusify: 1.1.0 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 - fill-range@7.1.1: + fix-dts-default-cjs-exports@1.0.1: dependencies: - to-regex-range: 5.0.1 + magic-string: 0.30.21 + mlly: 1.8.0 + rollup: 4.53.5 foreground-child@3.3.0: dependencies: @@ -1126,11 +1865,9 @@ snapshots: fsevents@2.3.3: optional: true - get-stream@6.0.1: {} - - glob-parent@5.1.2: + get-tsconfig@4.13.0: dependencies: - is-glob: 4.0.3 + resolve-pkg-maps: 1.0.0 glob@10.4.5: dependencies: @@ -1141,38 +1878,46 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - globby@11.1.0: + glob@13.0.0: dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 + minimatch: 10.1.1 + minipass: 7.1.2 + path-scurry: 2.0.1 - human-signals@2.1.0: {} + has-flag@4.0.0: {} - ignore@5.3.2: {} + hookable@6.0.1: {} - inherits@2.0.3: {} + html-escaper@2.0.2: {} - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 + import-without-cache@0.2.5: {} - is-extglob@2.1.1: {} + inherits@2.0.3: {} is-fullwidth-code-point@3.0.0: {} - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 + isexe@2.0.0: {} - is-number@7.0.0: {} + istanbul-lib-coverage@3.2.2: {} - is-stream@2.0.1: {} + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 - isexe@2.0.0: {} + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 jackspeak@3.4.3: dependencies: @@ -1182,26 +1927,37 @@ snapshots: joycon@3.1.1: {} + js-tokens@9.0.1: {} + + jsesc@3.1.0: {} + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} load-tsconfig@0.2.5: {} - lodash.sortby@4.7.0: {} - lru-cache@10.4.3: {} - merge-stream@2.0.0: {} + lru-cache@11.2.4: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 - merge2@1.4.1: {} + magicast@0.5.1: + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + source-map-js: 1.2.1 - micromatch@4.0.8: + make-dir@4.0.0: dependencies: - braces: 3.0.3 - picomatch: 2.3.1 + semver: 7.7.3 - mimic-fn@2.1.0: {} + minimatch@10.1.1: + dependencies: + '@isaacs/brace-expansion': 5.0.0 minimatch@9.0.5: dependencies: @@ -1211,6 +1967,13 @@ snapshots: mjml-browser@4.17.1: {} + mlly@1.8.0: + dependencies: + acorn: 8.15.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.1 + ms@2.1.3: {} mz@2.7.0: @@ -1219,17 +1982,11 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 + nanoid@3.3.11: {} object-assign@4.1.1: {} - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 + obug@2.1.1: {} package-json-from-dist@1.0.1: {} @@ -1242,22 +1999,43 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 - path-type@4.0.0: {} + path-scurry@2.0.1: + dependencies: + lru-cache: 11.2.4 + minipass: 7.1.2 path@0.12.7: dependencies: process: 0.11.10 util: 0.10.4 - picomatch@2.3.1: {} + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} pirates@4.0.6: {} - postcss-load-config@4.0.2: + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.0 + pathe: 2.0.3 + + postcss-load-config@6.0.1(postcss@8.5.6)(yaml@2.8.1): dependencies: lilconfig: 3.1.3 + optionalDependencies: + postcss: 8.5.6 yaml: 2.8.1 + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + pretty-bytes@7.1.0: {} pretty-ms@9.3.0: @@ -1266,46 +2044,78 @@ snapshots: process@0.11.10: {} - punycode@2.3.1: {} + quansync@1.0.0: {} - queue-microtask@1.2.3: {} - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 + readdirp@4.1.2: {} resolve-from@5.0.0: {} - reusify@1.1.0: {} + resolve-pkg-maps@1.0.0: {} - rollup@4.34.6: + rolldown-plugin-dts@0.19.1(rolldown@1.0.0-beta.55)(typescript@5.9.3): dependencies: - '@types/estree': 1.0.6 + '@babel/generator': 7.28.5 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + ast-kit: 2.2.0 + birpc: 4.0.0 + dts-resolver: 2.1.3 + get-tsconfig: 4.13.0 + obug: 2.1.1 + rolldown: 1.0.0-beta.55 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.34.6 - '@rollup/rollup-android-arm64': 4.34.6 - '@rollup/rollup-darwin-arm64': 4.34.6 - '@rollup/rollup-darwin-x64': 4.34.6 - '@rollup/rollup-freebsd-arm64': 4.34.6 - '@rollup/rollup-freebsd-x64': 4.34.6 - '@rollup/rollup-linux-arm-gnueabihf': 4.34.6 - '@rollup/rollup-linux-arm-musleabihf': 4.34.6 - '@rollup/rollup-linux-arm64-gnu': 4.34.6 - '@rollup/rollup-linux-arm64-musl': 4.34.6 - '@rollup/rollup-linux-loongarch64-gnu': 4.34.6 - '@rollup/rollup-linux-powerpc64le-gnu': 4.34.6 - '@rollup/rollup-linux-riscv64-gnu': 4.34.6 - '@rollup/rollup-linux-s390x-gnu': 4.34.6 - '@rollup/rollup-linux-x64-gnu': 4.34.6 - '@rollup/rollup-linux-x64-musl': 4.34.6 - '@rollup/rollup-win32-arm64-msvc': 4.34.6 - '@rollup/rollup-win32-ia32-msvc': 4.34.6 - '@rollup/rollup-win32-x64-msvc': 4.34.6 - fsevents: 2.3.3 + typescript: 5.9.3 + transitivePeerDependencies: + - oxc-resolver - run-parallel@1.2.0: + rolldown@1.0.0-beta.55: + dependencies: + '@oxc-project/types': 0.103.0 + '@rolldown/pluginutils': 1.0.0-beta.55 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.55 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.55 + '@rolldown/binding-darwin-x64': 1.0.0-beta.55 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.55 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.55 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.55 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.55 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.55 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.55 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.55 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.55 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.55 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.55 + + rollup@4.53.5: dependencies: - queue-microtask: 1.2.3 + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.53.5 + '@rollup/rollup-android-arm64': 4.53.5 + '@rollup/rollup-darwin-arm64': 4.53.5 + '@rollup/rollup-darwin-x64': 4.53.5 + '@rollup/rollup-freebsd-arm64': 4.53.5 + '@rollup/rollup-freebsd-x64': 4.53.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.5 + '@rollup/rollup-linux-arm-musleabihf': 4.53.5 + '@rollup/rollup-linux-arm64-gnu': 4.53.5 + '@rollup/rollup-linux-arm64-musl': 4.53.5 + '@rollup/rollup-linux-loong64-gnu': 4.53.5 + '@rollup/rollup-linux-ppc64-gnu': 4.53.5 + '@rollup/rollup-linux-riscv64-gnu': 4.53.5 + '@rollup/rollup-linux-riscv64-musl': 4.53.5 + '@rollup/rollup-linux-s390x-gnu': 4.53.5 + '@rollup/rollup-linux-x64-gnu': 4.53.5 + '@rollup/rollup-linux-x64-musl': 4.53.5 + '@rollup/rollup-openharmony-arm64': 4.53.5 + '@rollup/rollup-win32-arm64-msvc': 4.53.5 + '@rollup/rollup-win32-ia32-msvc': 4.53.5 + '@rollup/rollup-win32-x64-gnu': 4.53.5 + '@rollup/rollup-win32-x64-msvc': 4.53.5 + fsevents: 2.3.3 + + semver@7.7.3: {} shebang-command@2.0.0: dependencies: @@ -1313,15 +2123,17 @@ snapshots: shebang-regex@3.0.0: {} - signal-exit@3.0.7: {} + siginfo@2.0.0: {} signal-exit@4.1.0: {} - slash@3.0.0: {} + source-map-js@1.2.1: {} - source-map@0.8.0-beta.0: - dependencies: - whatwg-url: 7.1.0 + source-map@0.7.6: {} + + stackback@0.0.2: {} + + std-env@3.10.0: {} string-width@4.2.3: dependencies: @@ -1343,11 +2155,9 @@ snapshots: dependencies: ansi-regex: 6.1.0 - strip-final-newline@2.0.0: {} - sucrase@3.35.0: dependencies: - '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/gen-mapping': 0.3.13 commander: 4.1.1 glob: 10.4.5 lines-and-columns: 1.2.4 @@ -1355,6 +2165,103 @@ snapshots: pirates: 4.0.6 ts-interface-checker: 0.1.13 + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + text-camel-case@1.2.9: + dependencies: + text-pascal-case: 1.2.9 + + text-capital-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + text-upper-case-first: 1.2.9 + + text-case@1.2.9: + dependencies: + text-camel-case: 1.2.9 + text-capital-case: 1.2.9 + text-constant-case: 1.2.9 + text-dot-case: 1.2.9 + text-header-case: 1.2.9 + text-is-lower-case: 1.2.9 + text-is-upper-case: 1.2.9 + text-kebab-case: 1.2.9 + text-lower-case: 1.2.9 + text-lower-case-first: 1.2.9 + text-no-case: 1.2.9 + text-param-case: 1.2.9 + text-pascal-case: 1.2.9 + text-path-case: 1.2.9 + text-sentence-case: 1.2.9 + text-snake-case: 1.2.9 + text-swap-case: 1.2.9 + text-title-case: 1.2.9 + text-upper-case: 1.2.9 + text-upper-case-first: 1.2.9 + + text-constant-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + text-upper-case: 1.2.9 + + text-dot-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + + text-header-case@1.2.9: + dependencies: + text-capital-case: 1.2.9 + + text-is-lower-case@1.2.9: {} + + text-is-upper-case@1.2.9: {} + + text-kebab-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + + text-lower-case-first@1.2.9: {} + + text-lower-case@1.2.9: {} + + text-no-case@1.2.9: + dependencies: + text-lower-case: 1.2.9 + + text-param-case@1.2.9: + dependencies: + text-dot-case: 1.2.9 + + text-pascal-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + + text-path-case@1.2.9: + dependencies: + text-dot-case: 1.2.9 + + text-sentence-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + text-upper-case-first: 1.2.9 + + text-snake-case@1.2.9: + dependencies: + text-dot-case: 1.2.9 + + text-swap-case@1.2.9: {} + + text-title-case@1.2.9: + dependencies: + text-no-case: 1.2.9 + text-upper-case-first: 1.2.9 + + text-upper-case-first@1.2.9: {} + + text-upper-case@1.2.9: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -1363,58 +2270,161 @@ snapshots: dependencies: any-promise: 1.3.0 - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 + tinybench@2.9.0: {} - tr46@1.0.1: + tinyexec@0.3.2: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: dependencies: - punycode: 2.3.1 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinyrainbow@3.0.3: {} tree-kill@1.2.2: {} ts-interface-checker@0.1.13: {} - tsup@8.0.2(typescript@5.8.3): + tsdown@0.18.2(typescript@5.9.3): + dependencies: + ansis: 4.2.0 + cac: 6.7.14 + defu: 6.1.4 + empathic: 2.0.0 + hookable: 6.0.1 + import-without-cache: 0.2.5 + obug: 2.1.1 + picomatch: 4.0.3 + rolldown: 1.0.0-beta.55 + rolldown-plugin-dts: 0.19.1(rolldown@1.0.0-beta.55)(typescript@5.9.3) + semver: 7.7.3 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + unconfig-core: 7.4.2 + unrun: 0.2.20 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@ts-macro/tsc' + - '@typescript/native-preview' + - oxc-resolver + - synckit + - vue-tsc + + tslib@2.8.1: + optional: true + + tslog@4.10.2: {} + + tsup@8.5.1(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.1): dependencies: - bundle-require: 4.2.1(esbuild@0.19.12) + bundle-require: 5.1.0(esbuild@0.27.2) cac: 6.7.14 - chokidar: 3.6.0 + chokidar: 4.0.3 + consola: 3.4.2 debug: 4.4.0 - esbuild: 0.19.12 - execa: 5.1.1 - globby: 11.1.0 + esbuild: 0.27.2 + fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 - postcss-load-config: 4.0.2 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(postcss@8.5.6)(yaml@2.8.1) resolve-from: 5.0.0 - rollup: 4.34.6 - source-map: 0.8.0-beta.0 + rollup: 4.53.5 + source-map: 0.7.6 sucrase: 3.35.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 tree-kill: 1.2.2 optionalDependencies: - typescript: 5.8.3 + postcss: 8.5.6 + typescript: 5.9.3 transitivePeerDependencies: + - jiti - supports-color - - ts-node + - tsx + - yaml - typescript@5.8.3: {} + typescript@5.9.3: {} + + ufo@1.6.1: {} + + unconfig-core@7.4.2: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + + undici-types@7.16.0: {} + + unrun@0.2.20: + dependencies: + rolldown: 1.0.0-beta.55 util@0.10.4: dependencies: inherits: 2.0.3 - webidl-conversions@4.0.2: {} + vite@7.3.0(@types/node@25.0.3)(yaml@2.8.1): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.53.5 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.0.3 + fsevents: 2.3.3 + yaml: 2.8.1 - whatwg-url@7.1.0: + vitest@4.0.16(@types/node@25.0.3)(yaml@2.8.1): dependencies: - lodash.sortby: 4.7.0 - tr46: 1.0.1 - webidl-conversions: 4.0.2 + '@vitest/expect': 4.0.16 + '@vitest/mocker': 4.0.16(vite@7.3.0(@types/node@25.0.3)(yaml@2.8.1)) + '@vitest/pretty-format': 4.0.16 + '@vitest/runner': 4.0.16 + '@vitest/snapshot': 4.0.16 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.0(@types/node@25.0.3)(yaml@2.8.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.0.3 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml which@2.0.2: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -1427,4 +2437,5 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 - yaml@2.8.1: {} + yaml@2.8.1: + optional: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 8422fcf..89a7da1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,9 +1,11 @@ packages: - "examples/*" - - "packages/globe_runtime_ts" + - "packages/globe_runtime_ts/*" catalog: - tsup: 8.0.2 - typescript: 5.8.3 + tsup: 8.5.1 + tsdown: 0.18.1 + typescript: 5.9.3 fs: 0.0.1-security path: 0.12.7 + "@types/node": 25.0.3 diff --git a/src/dart_runtime.ts b/src/dart_runtime.ts index 49223e0..156835d 100644 --- a/src/dart_runtime.ts +++ b/src/dart_runtime.ts @@ -5,11 +5,13 @@ import { SendValueRequest, } from "./dart_runtime_entry.ts"; import * as msgPackr from "ext:js_msg_packr/index.js"; - -const { core } = Deno; +const { core } = Deno; -function register_js_module(moduleName: string, moduleFunctions: Record) { +function register_js_module( + moduleName: string, + moduleFunctions: Record +) { if (globalThis[moduleName]) { throw new Error(`Module "${moduleName}" is already registered.`); } @@ -47,7 +49,7 @@ class DartJSServiceImpl implements DartJSService { const _dartJSService = new DartJSServiceImpl(); -type DartValue = Uint8Array | undefined; +type DartValue = Uint8Array | undefined; register_js_module("Dart", { send_value: (callbackId: number, data: DartValue) => { @@ -62,7 +64,7 @@ register_js_module("Dart", { const message: DartMessage = { data, done: true }; return _dartJSService.SendValue({ callbackId, message }); }, - send_error: (callbackId:number, error: string) => { + send_error: (callbackId: number, error: string) => { const message: DartMessage = { error, done: true }; return _dartJSService.SendValue({ callbackId, message }); },