diff --git a/.gitignore b/.gitignore index 4b00baf..b8957ff 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,5 @@ example # generated native folders /ios /android +HANDOFF.md +DESIGN.md diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..ba708ed --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,10 @@ +// https://docs.expo.dev/guides/using-eslint/ +const { defineConfig } = require('eslint/config'); +const expoConfig = require("eslint-config-expo/flat"); + +module.exports = defineConfig([ + expoConfig, + { + ignores: ["dist/*"], + } +]); diff --git a/modules/astra-library-scanner/android/build.gradle b/modules/astra-library-scanner/android/build.gradle new file mode 100644 index 0000000..4498825 --- /dev/null +++ b/modules/astra-library-scanner/android/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'com.android.library' + id 'expo-module-gradle-plugin' +} + +group = 'expo.modules.astralibraryscanner' +version = '0.1.0' + +android { + namespace "expo.modules.astralibraryscanner" + defaultConfig { + versionCode 1 + versionName "0.1.0" + } + lintOptions { + abortOnError false + } +} diff --git a/modules/astra-library-scanner/android/build/.transforms/29ef0e4334b15aafef8157295d19f9ed/results.bin b/modules/astra-library-scanner/android/build/.transforms/29ef0e4334b15aafef8157295d19f9ed/results.bin new file mode 100644 index 0000000..0d259dd --- /dev/null +++ b/modules/astra-library-scanner/android/build/.transforms/29ef0e4334b15aafef8157295d19f9ed/results.bin @@ -0,0 +1 @@ +o/classes diff --git a/modules/astra-library-scanner/android/build/.transforms/29ef0e4334b15aafef8157295d19f9ed/transformed/classes/classes_dex/classes.dex b/modules/astra-library-scanner/android/build/.transforms/29ef0e4334b15aafef8157295d19f9ed/transformed/classes/classes_dex/classes.dex new file mode 100644 index 0000000..b17042e Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/29ef0e4334b15aafef8157295d19f9ed/transformed/classes/classes_dex/classes.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/results.bin b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/results.bin new file mode 100644 index 0000000..7ed749e --- /dev/null +++ b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/results.bin @@ -0,0 +1 @@ +o/bundleLibRuntimeToDirDebug diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.dex new file mode 100644 index 0000000..1639645 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.dex new file mode 100644 index 0000000..81fb500 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.dex new file mode 100644 index 0000000..ae47ae6 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.dex new file mode 100644 index 0000000..2025af2 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.dex new file mode 100644 index 0000000..26255d2 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.dex new file mode 100644 index 0000000..1a2ebe3 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.dex new file mode 100644 index 0000000..dfa4b5e Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.dex new file mode 100644 index 0000000..8b3ec22 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.dex new file mode 100644 index 0000000..b93a26c Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.dex new file mode 100644 index 0000000..49d2da3 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.dex new file mode 100644 index 0000000..382f941 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.dex new file mode 100644 index 0000000..d714625 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.dex new file mode 100644 index 0000000..65b3033 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.dex new file mode 100644 index 0000000..e93f809 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.dex new file mode 100644 index 0000000..42d7e35 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.dex new file mode 100644 index 0000000..5d8766c Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule.dex new file mode 100644 index 0000000..d447589 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/AstraLibraryScannerModule.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/BuildConfig.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/BuildConfig.dex new file mode 100644 index 0000000..ee0e39b Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/BuildConfig.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/FileRequest.dex b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/FileRequest.dex new file mode 100644 index 0000000..f591da7 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/astralibraryscanner/FileRequest.dex differ diff --git a/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin new file mode 100644 index 0000000..601f245 Binary files /dev/null and b/modules/astra-library-scanner/android/build/.transforms/382efa22b501a1f68234cf3c256624de/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin differ diff --git a/modules/astra-library-scanner/android/build/generated/source/buildConfig/debug/expo/modules/astralibraryscanner/BuildConfig.java b/modules/astra-library-scanner/android/build/generated/source/buildConfig/debug/expo/modules/astralibraryscanner/BuildConfig.java new file mode 100644 index 0000000..d39c7e1 --- /dev/null +++ b/modules/astra-library-scanner/android/build/generated/source/buildConfig/debug/expo/modules/astralibraryscanner/BuildConfig.java @@ -0,0 +1,10 @@ +/** + * Automatically generated file. DO NOT MODIFY + */ +package expo.modules.astralibraryscanner; + +public final class BuildConfig { + public static final boolean DEBUG = Boolean.parseBoolean("true"); + public static final String LIBRARY_PACKAGE_NAME = "expo.modules.astralibraryscanner"; + public static final String BUILD_TYPE = "debug"; +} diff --git a/modules/astra-library-scanner/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml b/modules/astra-library-scanner/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml new file mode 100644 index 0000000..8064d8b --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json b/modules/astra-library-scanner/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json new file mode 100644 index 0000000..6d196e2 --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json @@ -0,0 +1,18 @@ +{ + "version": 3, + "artifactType": { + "type": "AAPT_FRIENDLY_MERGED_MANIFESTS", + "kind": "Directory" + }, + "applicationId": "expo.modules.astralibraryscanner", + "variantName": "debug", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "attributes": [], + "outputFile": "AndroidManifest.xml" + } + ], + "elementType": "File" +} \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties b/modules/astra-library-scanner/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties new file mode 100644 index 0000000..1211b1e --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties @@ -0,0 +1,6 @@ +aarFormatVersion=1.0 +aarMetadataVersion=1.0 +minCompileSdk=1 +minCompileSdkExtension=0 +minAndroidGradlePluginVersion=1.0.0 +coreLibraryDesugaringEnabled=false diff --git a/modules/astra-library-scanner/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json b/modules/astra-library-scanner/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar b/modules/astra-library-scanner/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar new file mode 100644 index 0000000..64f5e42 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar differ diff --git a/modules/astra-library-scanner/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar b/modules/astra-library-scanner/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar new file mode 100644 index 0000000..8d14045 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar differ diff --git a/modules/astra-library-scanner/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt b/modules/astra-library-scanner/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt new file mode 100644 index 0000000..e69de29 diff --git a/modules/astra-library-scanner/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/modules/astra-library-scanner/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties new file mode 100644 index 0000000..83d3bce --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties @@ -0,0 +1 @@ +#Fri Jun 12 14:51:46 EDT 2026 diff --git a/modules/astra-library-scanner/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml b/modules/astra-library-scanner/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml new file mode 100644 index 0000000..f6fd81b --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugAssets/merger.xml b/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugAssets/merger.xml new file mode 100644 index 0000000..1eaa397 --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugAssets/merger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml b/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml new file mode 100644 index 0000000..70039c7 --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugShaders/merger.xml b/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugShaders/merger.xml new file mode 100644 index 0000000..205546d --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/incremental/mergeDebugShaders/merger.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/astra-library-scanner_debug.kotlin_module b/modules/astra-library-scanner/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/astra-library-scanner_debug.kotlin_module new file mode 100644 index 0000000..9dbc290 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/astra-library-scanner_debug.kotlin_module differ diff --git a/modules/astra-library-scanner/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/expo/modules/astralibraryscanner/BuildConfig.class b/modules/astra-library-scanner/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/expo/modules/astralibraryscanner/BuildConfig.class new file mode 100644 index 0000000..ad4e2cb Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/expo/modules/astralibraryscanner/BuildConfig.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt b/modules/astra-library-scanner/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt new file mode 100644 index 0000000..78ac5b8 --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt @@ -0,0 +1,2 @@ +R_DEF: Internal format may change without notice +local diff --git a/modules/astra-library-scanner/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt b/modules/astra-library-scanner/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt new file mode 100644 index 0000000..1f00ead --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt @@ -0,0 +1,7 @@ +1 +2 +4 +5 +6 +7 diff --git a/modules/astra-library-scanner/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml b/modules/astra-library-scanner/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml new file mode 100644 index 0000000..8064d8b --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json b/modules/astra-library-scanner/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt b/modules/astra-library-scanner/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt new file mode 100644 index 0000000..08f4ebe --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt @@ -0,0 +1 @@ +0 Warning/Error \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/astra-library-scanner_debug.kotlin_module b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/astra-library-scanner_debug.kotlin_module new file mode 100644 index 0000000..9dbc290 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/astra-library-scanner_debug.kotlin_module differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.class new file mode 100644 index 0000000..cc8c355 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.class new file mode 100644 index 0000000..451ef4c Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.class new file mode 100644 index 0000000..364569a Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.class new file mode 100644 index 0000000..bb21485 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.class new file mode 100644 index 0000000..f787913 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.class new file mode 100644 index 0000000..48304e1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.class new file mode 100644 index 0000000..d177720 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.class new file mode 100644 index 0000000..761452e Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.class new file mode 100644 index 0000000..5345370 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.class new file mode 100644 index 0000000..7c38978 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.class new file mode 100644 index 0000000..f21086c Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.class new file mode 100644 index 0000000..3cbaf50 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.class new file mode 100644 index 0000000..f607931 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.class new file mode 100644 index 0000000..441ba56 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.class new file mode 100644 index 0000000..35731a0 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.class new file mode 100644 index 0000000..eebcc6d Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule.class new file mode 100644 index 0000000..918cfb9 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/AstraLibraryScannerModule.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/BuildConfig.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/BuildConfig.class new file mode 100644 index 0000000..ad4e2cb Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/BuildConfig.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/FileRequest.class b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/FileRequest.class new file mode 100644 index 0000000..3c09c14 Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/astralibraryscanner/FileRequest.class differ diff --git a/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar new file mode 100644 index 0000000..e072e0a Binary files /dev/null and b/modules/astra-library-scanner/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar differ diff --git a/modules/astra-library-scanner/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt b/modules/astra-library-scanner/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt new file mode 100644 index 0000000..7e274f8 --- /dev/null +++ b/modules/astra-library-scanner/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt @@ -0,0 +1 @@ +expo.modules.astralibraryscanner diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab new file mode 100644 index 0000000..bdf584a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream new file mode 100644 index 0000000..4a0975a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len new file mode 100644 index 0000000..553b482 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len new file mode 100644 index 0000000..2a17e6e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at new file mode 100644 index 0000000..10c9a46 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i new file mode 100644 index 0000000..28d041a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab new file mode 100644 index 0000000..6edbe05 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream new file mode 100644 index 0000000..f195da2 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len new file mode 100644 index 0000000..c6582fd Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len new file mode 100644 index 0000000..01bdaa1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at new file mode 100644 index 0000000..fc0e221 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i new file mode 100644 index 0000000..3bbfd1f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab new file mode 100644 index 0000000..337da63 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream new file mode 100644 index 0000000..f195da2 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len new file mode 100644 index 0000000..c6582fd Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len new file mode 100644 index 0000000..01bdaa1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at new file mode 100644 index 0000000..93a4d48 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i new file mode 100644 index 0000000..3bbfd1f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab new file mode 100644 index 0000000..efcf01e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream new file mode 100644 index 0000000..893e61e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len new file mode 100644 index 0000000..c84115f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len new file mode 100644 index 0000000..09407ef Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at new file mode 100644 index 0000000..b358bdd Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i new file mode 100644 index 0000000..91b872b Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab new file mode 100644 index 0000000..6b364c9 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream new file mode 100644 index 0000000..6c3b7ea Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len new file mode 100644 index 0000000..6033372 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len new file mode 100644 index 0000000..a9f80ae Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at new file mode 100644 index 0000000..83514c7 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i new file mode 100644 index 0000000..bddc5b0 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab new file mode 100644 index 0000000..bdf584a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream new file mode 100644 index 0000000..4a0975a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len new file mode 100644 index 0000000..553b482 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len new file mode 100644 index 0000000..2a17e6e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at new file mode 100644 index 0000000..05afd1f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i new file mode 100644 index 0000000..28d041a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab new file mode 100644 index 0000000..1e11d35 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream new file mode 100644 index 0000000..7262ef0 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len new file mode 100644 index 0000000..b9d571f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len new file mode 100644 index 0000000..01bdaa1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at new file mode 100644 index 0000000..ca282fb Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i new file mode 100644 index 0000000..e71fada Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab new file mode 100644 index 0000000..6046526 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream new file mode 100644 index 0000000..bc273f6 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len new file mode 100644 index 0000000..bcd95fb Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len new file mode 100644 index 0000000..01bdaa1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at new file mode 100644 index 0000000..1416f69 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i new file mode 100644 index 0000000..3bbfd1f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab new file mode 100644 index 0000000..166c057 --- /dev/null +++ b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab @@ -0,0 +1,2 @@ +1 +0 \ No newline at end of file diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab new file mode 100644 index 0000000..bdf584a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream new file mode 100644 index 0000000..4a0975a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len new file mode 100644 index 0000000..553b482 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len new file mode 100644 index 0000000..2a17e6e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at new file mode 100644 index 0000000..5875372 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i new file mode 100644 index 0000000..28d041a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab new file mode 100644 index 0000000..8aad32b Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream new file mode 100644 index 0000000..08e7df1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len new file mode 100644 index 0000000..b7da01d Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len new file mode 100644 index 0000000..2a17e6e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at new file mode 100644 index 0000000..dec2d16 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len new file mode 100644 index 0000000..1b1cb4d Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab new file mode 100644 index 0000000..9ec5d60 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream new file mode 100644 index 0000000..5b3413f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len new file mode 100644 index 0000000..db84b4f Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len new file mode 100644 index 0000000..684cd78 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at new file mode 100644 index 0000000..27c740a Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i new file mode 100644 index 0000000..38cc63e Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len new file mode 100644 index 0000000..131e265 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin new file mode 100644 index 0000000..a2e03e8 Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin new file mode 100644 index 0000000..fa215cc Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin differ diff --git a/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin new file mode 100644 index 0000000..d1406ef Binary files /dev/null and b/modules/astra-library-scanner/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin differ diff --git a/modules/astra-library-scanner/android/build/outputs/logs/manifest-merger-debug-report.txt b/modules/astra-library-scanner/android/build/outputs/logs/manifest-merger-debug-report.txt new file mode 100644 index 0000000..470ee5f --- /dev/null +++ b/modules/astra-library-scanner/android/build/outputs/logs/manifest-merger-debug-report.txt @@ -0,0 +1,14 @@ +-- Merging decision tree log --- +manifest +ADDED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml:1:1-2:12 +INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml:1:1-2:12 + package + INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml +uses-sdk +INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml reason: use-sdk injection requested +INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml +INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml + android:targetSdkVersion + INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml + android:minSdkVersion + INJECTED from /Users/landerhartel/Documents/astra/astra-mobile/modules/astra-library-scanner/android/src/main/AndroidManifest.xml diff --git a/modules/astra-library-scanner/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin b/modules/astra-library-scanner/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin new file mode 100644 index 0000000..d7ffd94 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/META-INF/astra-library-scanner_debug.kotlin_module b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/META-INF/astra-library-scanner_debug.kotlin_module new file mode 100644 index 0000000..9dbc290 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/META-INF/astra-library-scanner_debug.kotlin_module differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.class new file mode 100644 index 0000000..cc8c355 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$1$1.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.class new file mode 100644 index 0000000..451ef4c Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1$1$1.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.class new file mode 100644 index 0000000..364569a Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$1$2$1.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.class new file mode 100644 index 0000000..bb21485 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$1.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.class new file mode 100644 index 0000000..f787913 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$2.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.class new file mode 100644 index 0000000..48304e1 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$3.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.class new file mode 100644 index 0000000..d177720 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$4.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.class new file mode 100644 index 0000000..761452e Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$5.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.class new file mode 100644 index 0000000..5345370 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$AsyncFunction$6.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.class new file mode 100644 index 0000000..7c38978 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$1.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.class new file mode 100644 index 0000000..f21086c Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$2.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.class new file mode 100644 index 0000000..3cbaf50 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$3.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.class new file mode 100644 index 0000000..f607931 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$4.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.class new file mode 100644 index 0000000..441ba56 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$Coroutine$5.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.class new file mode 100644 index 0000000..35731a0 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$1.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.class new file mode 100644 index 0000000..eebcc6d Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule$definition$lambda$8$$inlined$FunctionWithoutArgs$2.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule.class new file mode 100644 index 0000000..918cfb9 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/AstraLibraryScannerModule.class differ diff --git a/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/FileRequest.class b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/FileRequest.class new file mode 100644 index 0000000..3c09c14 Binary files /dev/null and b/modules/astra-library-scanner/android/build/tmp/kotlin-classes/debug/expo/modules/astralibraryscanner/FileRequest.class differ diff --git a/modules/astra-library-scanner/android/src/main/AndroidManifest.xml b/modules/astra-library-scanner/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..bdae66c --- /dev/null +++ b/modules/astra-library-scanner/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/modules/astra-library-scanner/android/src/main/java/expo/modules/astralibraryscanner/AstraLibraryScannerModule.kt b/modules/astra-library-scanner/android/src/main/java/expo/modules/astralibraryscanner/AstraLibraryScannerModule.kt new file mode 100644 index 0000000..f582291 --- /dev/null +++ b/modules/astra-library-scanner/android/src/main/java/expo/modules/astralibraryscanner/AstraLibraryScannerModule.kt @@ -0,0 +1,341 @@ +package expo.modules.astralibraryscanner + +import android.content.Context +import android.content.Intent +import android.media.AudioFormat +import android.media.MediaExtractor +import android.media.MediaFormat +import android.media.MediaMetadataRetriever +import android.net.Uri +import android.os.Build +import android.provider.DocumentsContract +import expo.modules.kotlin.exception.Exceptions +import expo.modules.kotlin.functions.Coroutine +import expo.modules.kotlin.modules.Module +import expo.modules.kotlin.modules.ModuleDefinition +import expo.modules.kotlin.records.Field +import expo.modules.kotlin.records.Record +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.sync.Semaphore +import kotlinx.coroutines.sync.withPermit +import kotlinx.coroutines.withContext +import java.io.File +import java.security.MessageDigest +import java.util.concurrent.ConcurrentHashMap + +class FileRequest : Record { + @Field val uri: String = "" + @Field val coverUri: String? = null +} + +class AstraLibraryScannerModule : Module() { + // Cover-art hashes memoized per cover URI for the duration of one scan + // (cleared on each listAudioFiles call) so an album folder's cover.jpg is + // read and hashed once, not once per track. + private val coverHashMemo = ConcurrentHashMap() + + override fun definition() = ModuleDefinition { + Name("AstraLibraryScanner") + + Events("onScanProgress") + + AsyncFunction("listAudioFiles") Coroutine { treeUri: String, extensions: List -> + withContext(Dispatchers.IO) { listAudioFiles(treeUri, extensions) } + } + + AsyncFunction("extractMetadata") Coroutine { files: List -> + val semaphore = Semaphore(4) + coroutineScope { + files.map { request -> + async(Dispatchers.IO) { semaphore.withPermit { extractOne(request) } } + }.awaitAll() + } + } + + Function("getArtworkDirPath") { + artworkDir().absolutePath + } + + Function("getPersistedTreeUris") { + requireContext().contentResolver.persistedUriPermissions + .filter { it.isReadPermission } + .map { it.uri.toString() } + } + + AsyncFunction("takePersistableUriPermission") { uri: String -> + try { + requireContext().contentResolver.takePersistableUriPermission( + Uri.parse(uri), + Intent.FLAG_GRANT_READ_URI_PERMISSION + ) + true + } catch (t: Throwable) { + false + } + } + + AsyncFunction("releasePersistedUriPermission") { uri: String -> + try { + requireContext().contentResolver.releasePersistableUriPermission( + Uri.parse(uri), + Intent.FLAG_GRANT_READ_URI_PERMISSION + ) + } catch (_: Throwable) { + // Already released or never persisted — nothing to do. + } + } + } + + private fun requireContext(): Context = + appContext.reactContext ?: throw Exceptions.ReactContextLost() + + private fun artworkDir(): File = + File(requireContext().filesDir, "artwork").apply { if (!exists()) mkdirs() } + + // --------------------------------------------------------------------------- + // Directory walk + // --------------------------------------------------------------------------- + + private val coverBaseNames = listOf("cover", "folder", "front", "albumart") + private val coverExtensions = setOf("jpg", "jpeg", "png", "webp") + + private fun listAudioFiles(treeUri: String, extensions: List): Map { + coverHashMemo.clear() + + val resolver = requireContext().contentResolver + val tree = Uri.parse(treeUri) + val extensionSet = extensions.map { it.lowercase() }.toSet() + + val projection = arrayOf( + DocumentsContract.Document.COLUMN_DOCUMENT_ID, + DocumentsContract.Document.COLUMN_DISPLAY_NAME, + DocumentsContract.Document.COLUMN_MIME_TYPE, + DocumentsContract.Document.COLUMN_SIZE, + DocumentsContract.Document.COLUMN_LAST_MODIFIED + ) + + val files = mutableListOf>() + // parent document uri -> (cover rank, cover document uri); lower rank wins + val covers = mutableMapOf>() + + val queue = ArrayDeque() + queue.add(DocumentsContract.getTreeDocumentId(tree)) + + while (queue.isNotEmpty()) { + val dirDocId = queue.removeFirst() + val parentUri = DocumentsContract.buildDocumentUriUsingTree(tree, dirDocId).toString() + val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(tree, dirDocId) + + val cursor = resolver.query(childrenUri, projection, null, null, null) + ?: continue // directory disappeared mid-walk; skip it + cursor.use { + while (it.moveToNext()) { + val docId = it.getString(0) ?: continue + val name = it.getString(1) ?: continue + val mime = it.getString(2) ?: "" + + if (mime == DocumentsContract.Document.MIME_TYPE_DIR) { + queue.add(docId) + continue + } + + val extension = name.substringAfterLast('.', "").lowercase() + if (extension in extensionSet) { + files.add( + mapOf( + "uri" to DocumentsContract.buildDocumentUriUsingTree(tree, docId).toString(), + "name" to name, + "size" to if (it.isNull(3)) null else it.getLong(3), + "lastModified" to if (it.isNull(4)) 0L else it.getLong(4), + "mimeType" to mime.ifEmpty { null }, + "parentUri" to parentUri + ) + ) + if (files.size % 100 == 0) { + sendEvent("onScanProgress", mapOf("phase" to "discovering", "found" to files.size)) + } + } else if (extension in coverExtensions) { + val rank = coverBaseNames.indexOf(name.substringBeforeLast('.').lowercase()) + if (rank >= 0) { + val existing = covers[parentUri] + if (existing == null || rank < existing.first) { + covers[parentUri] = + rank to DocumentsContract.buildDocumentUriUsingTree(tree, docId).toString() + } + } + } + } + } + } + + sendEvent("onScanProgress", mapOf("phase" to "discovering", "found" to files.size)) + + return mapOf( + "files" to files, + "covers" to covers.mapValues { (_, ranked) -> ranked.second } + ) + } + + // --------------------------------------------------------------------------- + // Metadata extraction + // --------------------------------------------------------------------------- + + private fun extractOne(request: FileRequest): Map { + val context = requireContext() + val uri = Uri.parse(request.uri) + val result = mutableMapOf("uri" to request.uri, "ok" to true) + + var embeddedPicture: ByteArray? = null + val retriever = MediaMetadataRetriever() + try { + retriever.setDataSource(context, uri) + + result["title"] = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE) + result["artist"] = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST) + result["album"] = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM) + result["albumArtist"] = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST) + result["genre"] = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE) + result["mimeType"] = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE) + result["durationMs"] = + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() + result["bitrate"] = + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE)?.toIntOrNull() + result["trackNumber"] = parseTagNumber( + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER) + ) + result["discNumber"] = parseTagNumber( + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER) + ) + result["year"] = parseYear( + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR), + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE) + ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + result["sampleRate"] = + retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_SAMPLERATE)?.toIntOrNull() + } + embeddedPicture = retriever.embeddedPicture + } catch (t: Throwable) { + return mapOf( + "uri" to request.uri, + "ok" to false, + "error" to (t.message ?: t.javaClass.simpleName) + ) + } finally { + try { + retriever.release() + } catch (_: Throwable) {} + } + + // Header-level facts MMR can't provide (channels, bit depth) or only on + // API 31+ (sample rate). Failure here is non-fatal — keep the tag data. + val extractor = MediaExtractor() + try { + extractor.setDataSource(context, uri, null) + for (i in 0 until extractor.trackCount) { + val format = extractor.getTrackFormat(i) + val trackMime = format.getString(MediaFormat.KEY_MIME) ?: continue + if (!trackMime.startsWith("audio/")) continue + + result["codecMime"] = trackMime + if (format.containsKey(MediaFormat.KEY_CHANNEL_COUNT)) { + result["channels"] = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT) + } + if (result["sampleRate"] == null && format.containsKey(MediaFormat.KEY_SAMPLE_RATE)) { + result["sampleRate"] = format.getInteger(MediaFormat.KEY_SAMPLE_RATE) + } + result["bitsPerSample"] = readBitsPerSample(format) + break + } + } catch (_: Throwable) { + // Container not supported by MediaExtractor — tag data already collected. + } finally { + try { + extractor.release() + } catch (_: Throwable) {} + } + + try { + result["artworkHash"] = resolveArtwork(embeddedPicture, request.coverUri) + } catch (_: Throwable) { + // Artwork failure never fails the track. + } + + return result + } + + private fun readBitsPerSample(format: MediaFormat): Int? { + // The framework FLAC/WAV extractors expose "bits-per-sample"; other codecs + // may expose a PCM encoding instead. Both are best-effort. + if (format.containsKey("bits-per-sample")) { + return format.getInteger("bits-per-sample") + } + if (format.containsKey(MediaFormat.KEY_PCM_ENCODING)) { + return when (format.getInteger(MediaFormat.KEY_PCM_ENCODING)) { + AudioFormat.ENCODING_PCM_8BIT -> 8 + AudioFormat.ENCODING_PCM_16BIT -> 16 + AudioFormat.ENCODING_PCM_24BIT_PACKED -> 24 + AudioFormat.ENCODING_PCM_32BIT, AudioFormat.ENCODING_PCM_FLOAT -> 32 + else -> null + } + } + return null + } + + private fun parseTagNumber(raw: String?): Int? = + raw?.split('/')?.firstOrNull()?.trim()?.toIntOrNull()?.takeIf { it > 0 } + + private fun parseYear(year: String?, date: String?): Int? { + for (candidate in listOf(year, date)) { + if (candidate == null) continue + val match = Regex("\\d{4}").find(candidate) ?: continue + return match.value.toIntOrNull() + } + return null + } + + // --------------------------------------------------------------------------- + // Artwork cache (mirrors desktop: file name = md5(bytes) + extension) + // --------------------------------------------------------------------------- + + private fun resolveArtwork(embedded: ByteArray?, coverUri: String?): String? { + if (embedded != null && embedded.isNotEmpty()) { + return writeArtwork(embedded) + } + if (coverUri == null) return null + return coverHashMemo.getOrPut(coverUri) { + val bytes = requireContext().contentResolver.openInputStream(Uri.parse(coverUri)) + ?.use { it.readBytes() } + ?: return null + if (bytes.isEmpty()) return null + writeArtwork(bytes) + } + } + + private fun writeArtwork(bytes: ByteArray): String { + val fileName = md5Hex(bytes) + sniffImageExtension(bytes) + val target = File(artworkDir(), fileName) + if (!target.exists()) { + val temp = File(artworkDir(), "$fileName.tmp-${Thread.currentThread().id}") + temp.writeBytes(bytes) + if (!temp.renameTo(target)) { + temp.delete() + } + } + return fileName + } + + private fun md5Hex(bytes: ByteArray): String = + MessageDigest.getInstance("MD5").digest(bytes).joinToString("") { "%02x".format(it) } + + private fun sniffImageExtension(bytes: ByteArray): String = when { + bytes.size >= 2 && bytes[0] == 0xFF.toByte() && bytes[1] == 0xD8.toByte() -> ".jpg" + bytes.size >= 4 && bytes[0] == 0x89.toByte() && bytes[1] == 0x50.toByte() -> ".png" + bytes.size >= 12 && bytes[8] == 'W'.code.toByte() && bytes[9] == 'E'.code.toByte() && + bytes[10] == 'B'.code.toByte() && bytes[11] == 'P'.code.toByte() -> ".webp" + else -> ".jpg" + } +} diff --git a/modules/astra-library-scanner/expo-module.config.json b/modules/astra-library-scanner/expo-module.config.json new file mode 100644 index 0000000..a058789 --- /dev/null +++ b/modules/astra-library-scanner/expo-module.config.json @@ -0,0 +1,6 @@ +{ + "platforms": ["android"], + "android": { + "modules": ["expo.modules.astralibraryscanner.AstraLibraryScannerModule"] + } +} diff --git a/modules/astra-library-scanner/index.ts b/modules/astra-library-scanner/index.ts new file mode 100644 index 0000000..eefde6a --- /dev/null +++ b/modules/astra-library-scanner/index.ts @@ -0,0 +1,65 @@ +import { requireNativeModule, type NativeModule } from 'expo-modules-core'; + +/** A single audio file found during the SAF tree walk. */ +export interface ScannedFile { + /** SAF document URI — playable directly by ExoPlayer and readable by MMR. */ + uri: string; + name: string; + size: number | null; + lastModified: number; + mimeType: string | null; + /** Document URI of the containing directory (key into `ListResult.covers`). */ + parentUri: string; +} + +export interface ListResult { + files: ScannedFile[]; + /** Best external cover-art candidate per directory (cover/folder/front/albumart). */ + covers: Record; +} + +export interface ExtractedMetadata { + uri: string; + ok: boolean; + error?: string; + title?: string | null; + artist?: string | null; + album?: string | null; + albumArtist?: string | null; + genre?: string | null; + /** Container mime type reported by MediaMetadataRetriever. */ + mimeType?: string | null; + /** Audio track mime type from MediaExtractor (e.g. "audio/flac"). */ + codecMime?: string | null; + durationMs?: number | null; + bitrate?: number | null; + trackNumber?: number | null; + discNumber?: number | null; + year?: number | null; + sampleRate?: number | null; + channels?: number | null; + bitsPerSample?: number | null; + /** File name in the artwork cache dir: `md5(bytes) + extension`. */ + artworkHash?: string | null; +} + +export interface ScanProgressEvent { + phase: 'discovering'; + found: number; +} + +type AstraLibraryScannerEvents = { + onScanProgress: (event: ScanProgressEvent) => void; +}; + +declare class AstraLibraryScannerModuleType extends NativeModule { + listAudioFiles(treeUri: string, extensions: string[]): Promise; + extractMetadata(files: { uri: string; coverUri?: string | null }[]): Promise; + getArtworkDirPath(): string; + getPersistedTreeUris(): string[]; + takePersistableUriPermission(uri: string): Promise; + releasePersistedUriPermission(uri: string): Promise; +} + +export const AstraLibraryScanner = + requireNativeModule('AstraLibraryScanner'); diff --git a/package-lock.json b/package-lock.json index 56850a8..cf5d2fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,15 +7,19 @@ "": { "name": "astra-mobile", "version": "0.1.0", + "hasInstallScript": true, "dependencies": { "@expo-google-fonts/inter": "^0.4.2", "@expo-google-fonts/jetbrains-mono": "^0.4.1", "@expo/ui": "~56.0.13", "@expo/vector-icons": "^15.0.2", + "@op-engineering/op-sqlite": "^16.2.1", + "@shopify/flash-list": "2.0.2", "expo": "~56.0.4", "expo-asset": "~56.0.14", "expo-constants": "~56.0.15", "expo-device": "~56.0.4", + "expo-file-system": "~56.0.8", "expo-font": "~56.0.5", "expo-glass-effect": "~56.0.4", "expo-image": "~56.0.9", @@ -41,6 +45,8 @@ }, "devDependencies": { "@types/react": "~19.2.2", + "eslint": "^9.0.0", + "eslint-config-expo": "~56.0.4", "patch-package": "^8.0.1", "typescript": "~6.0.3" } @@ -1156,6 +1162,246 @@ "node": ">=0.8.0" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@expo-google-fonts/inter": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@expo-google-fonts/inter/-/inter-0.4.2.tgz", @@ -1711,6 +1957,72 @@ "excpretty": "build/cli.js" } }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@isaacs/ttlcache": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", @@ -1882,6 +2194,55 @@ "win32" ] }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", + "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@op-engineering/op-sqlite": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@op-engineering/op-sqlite/-/op-sqlite-16.2.1.tgz", + "integrity": "sha512-mDMdvAJJ97XfmJRKxzldyR9OpADmPVDofOWRgcB+kN1mlKmNkoJMZnX5SDYsYUki215FZkXzevExuhSzfyEWLw==", + "license": "MIT", + "workspaces": [ + "example", + "node" + ], + "peerDependencies": { + "@sqlite.org/sqlite-wasm": "*", + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "@sqlite.org/sqlite-wasm": { + "optional": true + } + } + }, "node_modules/@radix-ui/primitive": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", @@ -2640,6 +3001,27 @@ } } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@shopify/flash-list": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-2.0.2.tgz", + "integrity": "sha512-zhlrhA9eiuEzja4wxVvotgXHtqd3qsYbXkQ3rsBfOgbFA9BVeErpDE/yEwtlIviRGEqpuFj/oU5owD6ByaNX+w==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "peerDependencies": { + "@babel/runtime": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.10", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", @@ -2739,6 +3121,17 @@ "@testing-library/dom": ">=7.21.4" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -2746,6 +3139,13 @@ "license": "MIT", "peer": true }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/hammerjs": { "version": "2.0.46", "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", @@ -2776,6 +3176,20 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "25.9.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", @@ -2818,12 +3232,581 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.0.tgz", + "integrity": "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/type-utils": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.61.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.0.tgz", + "integrity": "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.0.tgz", + "integrity": "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.61.0", + "@typescript-eslint/types": "^8.61.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.0.tgz", + "integrity": "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.0.tgz", + "integrity": "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.0.tgz", + "integrity": "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0", + "@typescript-eslint/utils": "8.61.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.0.tgz", + "integrity": "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.0.tgz", + "integrity": "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.61.0", + "@typescript-eslint/tsconfig-utils": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/visitor-keys": "8.61.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.0.tgz", + "integrity": "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.61.0", + "@typescript-eslint/types": "8.61.0", + "@typescript-eslint/typescript-estree": "8.61.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.61.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.0.tgz", + "integrity": "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", "license": "ISC" }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@xmldom/xmldom": { "version": "0.8.13", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", @@ -2877,6 +3860,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -2886,6 +3879,23 @@ "node": ">= 14" } }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/anser": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", @@ -2976,12 +3986,198 @@ "dequal": "^2.0.3" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "license": "MIT" }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.17", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", @@ -3329,6 +4525,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -3571,6 +4777,13 @@ "node": ">= 0.6" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, "node_modules/connect": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", @@ -3714,6 +4927,60 @@ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -3740,6 +5007,13 @@ "node": ">=0.10" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -3779,6 +5053,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3828,6 +5120,19 @@ "integrity": "sha512-AmGyK9WpNf06WeP5TjHZq/wNzP76OuEeaiTlKr9E/EEelYLczywUKoqRz+DPRq/ErssjT4lU+/W7wzJW+7K/ZA==", "license": "MIT" }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -3953,6 +5258,75 @@ "stackframe": "^1.3.4" } }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -3972,6 +5346,34 @@ "node": ">= 0.4" } }, + "node_modules/es-iterator-helpers": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz", + "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-object-atoms": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", @@ -3985,6 +5387,53 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -4012,6 +5461,551 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-expo": { + "version": "56.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-expo/-/eslint-config-expo-56.0.4.tgz", + "integrity": "sha512-1OD7rJMxCchKHxq+U+OQsAxVtzAxeUb9875g6+15KsSD9fqKTgq7DEEWYwunzU9r9E8kYJ+mh7+j86vF9m9NMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^8.59.0", + "@typescript-eslint/parser": "^8.59.0", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-expo": "^1.0.1", + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-react": "^7.37.3", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "^16.0.0" + }, + "peerDependencies": { + "eslint": ">=8.10" + } + }, + "node_modules/eslint-config-expo/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.13.0.tgz", + "integrity": "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-expo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-expo/-/eslint-plugin-expo-1.0.3.tgz", + "integrity": "sha512-C1v9NPvpDET36+7Klpp/+53Jl+VzOfpbDxpKtL/pAPhCDwTX0kW6Swo425PT0uc4AMT5jpQbB7hSKFjKOGMl4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.29.1", + "@typescript-eslint/utils": "^8.29.1", + "eslint": "^9.24.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": ">=8.10" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react-hooks/node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-react-hooks/node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -4133,9 +6127,9 @@ } }, "node_modules/expo-file-system": { - "version": "56.0.7", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-56.0.7.tgz", - "integrity": "sha512-dcKzo8ShPloM7jgfnMcJStgQebhP8owVjCkNI/aX6NMFV1CYB8bxKGMdnzJ3mXk5nfaiW+F/lSKr2UIJ02WAUA==", + "version": "56.0.8", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-56.0.8.tgz", + "integrity": "sha512-NrH41/8snGIBSbYicwVLB4txPdgCATd7ZYhMAGS3YJZ9GbnduhlAoV4/YCbGayjrbpE9bJb/6wegPL/zmvRMnQ==", "license": "MIT", "peerDependencies": { "expo": "*", @@ -4627,6 +6621,20 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fb-dotslash": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", @@ -4727,6 +6735,19 @@ "integrity": "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==", "license": "MIT" }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4781,6 +6802,23 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", @@ -4791,6 +6829,27 @@ "micromatch": "^4.0.2" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, "node_modules/flow-enums-runtime": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", @@ -4803,6 +6862,22 @@ "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", "license": "BSD-2-Clause" }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -4836,6 +6911,50 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4902,6 +7021,37 @@ "node": ">= 0.4" } }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/getenv": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz", @@ -4928,6 +7078,49 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -4947,6 +7140,19 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4969,6 +7175,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -4982,10 +7204,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", - "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5120,6 +7358,43 @@ "node": ">=16.x" } }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", @@ -5144,6 +7419,21 @@ "css-in-js-utils": "^3.1.0" } }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -5153,12 +7443,119 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT" }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.16.2", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", @@ -5174,6 +7571,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -5189,6 +7621,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -5198,6 +7672,65 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -5207,6 +7740,168 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -5232,6 +7927,24 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -5374,6 +8087,20 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/json-stable-stringify": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", @@ -5394,6 +8121,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5429,6 +8163,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/klaw-sync": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", @@ -5466,6 +8226,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lighthouse-logger": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", @@ -5740,12 +8514,35 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -6394,6 +9191,29 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -6403,6 +9223,25 @@ "node": ">= 0.6" } }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -6528,6 +9367,19 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -6538,6 +9390,96 @@ "node": ">= 0.4" } }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -6587,6 +9529,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", @@ -6696,6 +9656,69 @@ "node": ">=4" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-png": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", @@ -6776,6 +9799,16 @@ "node": ">=10" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6866,6 +9899,16 @@ "node": ">=4.0.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.15", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", @@ -6900,6 +9943,16 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -6972,6 +10025,35 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/query-string": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", @@ -7434,6 +10516,29 @@ "node": ">=8" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -7458,6 +10563,27 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "license": "MIT" }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpu-core": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", @@ -7532,6 +10658,16 @@ "node": ">=8" } }, + "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==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve-workspace-root": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz", @@ -7551,6 +10687,26 @@ "node": ">=4" } }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7571,6 +10727,41 @@ ], "license": "MIT" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/sax": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", @@ -7721,6 +10912,37 @@ "node": ">= 0.4" } }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -7781,6 +11003,82 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -7878,6 +11176,13 @@ "node": ">=6" } }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -7905,6 +11210,20 @@ "node": ">= 0.6" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-buffers": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", @@ -7937,6 +11256,105 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -7949,6 +11367,16 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -7961,6 +11389,19 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/structured-headers": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", @@ -8121,12 +11562,64 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "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" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", @@ -8136,6 +11629,84 @@ "node": ">=8" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", @@ -8176,6 +11747,25 @@ "node": "*" } }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", @@ -8241,6 +11831,44 @@ "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -8271,6 +11899,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -8446,6 +12084,105 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -8585,6 +12322,19 @@ "node": ">=12" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", @@ -8594,6 +12344,19 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, "node_modules/zustand": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.13.tgz", diff --git a/package.json b/package.json index 84cfc92..4cb8a67 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,13 @@ "@expo-google-fonts/jetbrains-mono": "^0.4.1", "@expo/ui": "~56.0.13", "@expo/vector-icons": "^15.0.2", + "@op-engineering/op-sqlite": "^16.2.1", + "@shopify/flash-list": "2.0.2", "expo": "~56.0.4", "expo-asset": "~56.0.14", "expo-constants": "~56.0.15", "expo-device": "~56.0.4", + "expo-file-system": "~56.0.8", "expo-font": "~56.0.5", "expo-glass-effect": "~56.0.4", "expo-image": "~56.0.9", @@ -36,6 +39,8 @@ }, "devDependencies": { "@types/react": "~19.2.2", + "eslint": "^9.0.0", + "eslint-config-expo": "~56.0.4", "patch-package": "^8.0.1", "typescript": "~6.0.3" }, diff --git a/src/app/(tabs)/library.tsx b/src/app/(tabs)/library.tsx deleted file mode 100644 index 6c5c11f..0000000 --- a/src/app/(tabs)/library.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { View, StyleSheet } from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import { Screen } from '@/components/Screen'; -import { Text } from '@/components/Text'; -import { colors, spacing } from '@/theme'; - -export default function LibraryScreen() { - return ( - - - Library - - - - - - No music yet - - - On-device file scanning, metadata, and the SQLite library arrive in M1. - - - - ); -} - -const styles = StyleSheet.create({ - heading: { - marginTop: spacing.xl, - marginBottom: spacing.lg, - }, - empty: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - gap: spacing.sm, - paddingBottom: spacing.xxl, - }, - emptyTitle: { - marginTop: spacing.sm, - }, - emptyBody: { - textAlign: 'center', - maxWidth: 280, - }, -}); diff --git a/src/app/(tabs)/library/_layout.tsx b/src/app/(tabs)/library/_layout.tsx new file mode 100644 index 0000000..83967f7 --- /dev/null +++ b/src/app/(tabs)/library/_layout.tsx @@ -0,0 +1,17 @@ +import { Stack } from 'expo-router'; +import { colors } from '@/theme'; + +/** + * Nested stack inside the Library tab so album/artist detail screens keep the + * tab bar + mini-player visible. + */ +export default function LibraryLayout() { + return ( + + ); +} diff --git a/src/app/(tabs)/library/album/[key].tsx b/src/app/(tabs)/library/album/[key].tsx new file mode 100644 index 0000000..e0f776c --- /dev/null +++ b/src/app/(tabs)/library/album/[key].tsx @@ -0,0 +1,153 @@ +import { useMemo } from 'react'; +import { View, Pressable, StyleSheet } from 'react-native'; +import { Image } from 'expo-image'; +import { Ionicons } from '@expo/vector-icons'; +import { FlashList } from '@shopify/flash-list'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { Screen } from '@/components/Screen'; +import { Text } from '@/components/Text'; +import { AstraLogo } from '@/components/AstraLogo'; +import { TrackRow } from '@/components/library/TrackRow'; +import { colors, radius, spacing } from '@/theme'; +import { useLibraryStore } from '@/stores/libraryStore'; +import { usePlayerStore } from '@/stores/playerStore'; +import { playTracks } from '@/audio/playbackController'; +import { dbTrackToTrack } from '@/library/trackAdapter'; +import { artworkUri } from '@/library/artwork'; +import { formatDuration } from '@/lib/format'; + +export default function AlbumScreen() { + const router = useRouter(); + const { key } = useLocalSearchParams<{ key: string }>(); + const albums = useLibraryStore((s) => s.albums); + const allTracks = useLibraryStore((s) => s.tracks); + const currentPath = usePlayerStore((s) => s.currentTrack?.path); + + const album = albums.find((entry) => entry.identity_key === key); + // Store tracks are ordered artist/album/disc/track, so the filtered slice + // keeps disc/track order within one album. + const tracks = useMemo( + () => allTracks.filter((track) => track.album_identity_key === key), + [allTracks, key] + ); + + const totalDuration = tracks.reduce((sum, track) => sum + track.duration, 0); + + const playFrom = (index: number) => { + void playTracks(tracks.map(dbTrackToTrack), index); + }; + + return ( + + router.back()} hitSlop={8}> + + + Library + + + + + + {album?.artwork_hash ? ( + + ) : ( + + )} + + + + {album?.album ?? 'Album'} + + + {album?.artist ?? ''} + + + {[ + album?.year ? String(album.year) : null, + `${tracks.length} ${tracks.length === 1 ? 'track' : 'tracks'}`, + formatDuration(totalDuration), + ] + .filter(Boolean) + .join(' · ')} + + playFrom(0)} accessibilityRole="button"> + + + Play + + + + + + String(track.id)} + showsVerticalScrollIndicator={false} + renderItem={({ item, index }) => ( + playFrom(index)} + /> + )} + /> + + ); +} + +const styles = StyleSheet.create({ + back: { + flexDirection: 'row', + alignItems: 'center', + gap: 2, + marginTop: spacing.md, + marginBottom: spacing.md, + alignSelf: 'flex-start', + }, + header: { + flexDirection: 'row', + gap: spacing.lg, + marginBottom: spacing.lg, + }, + art: { + width: 128, + height: 128, + borderRadius: radius.md, + backgroundColor: colors.bgTertiary, + borderColor: colors.glassBorder, + borderWidth: StyleSheet.hairlineWidth, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + }, + artImage: { + width: '100%', + height: '100%', + }, + headerMeta: { + flex: 1, + justifyContent: 'center', + gap: spacing.xs, + }, + playButton: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing.xs, + backgroundColor: colors.accent, + borderRadius: radius.pill, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm, + alignSelf: 'flex-start', + marginTop: spacing.xs, + }, + playLabel: { + color: colors.bgPrimary, + fontWeight: '600', + }, +}); diff --git a/src/app/(tabs)/library/artist/[name].tsx b/src/app/(tabs)/library/artist/[name].tsx new file mode 100644 index 0000000..e265f21 --- /dev/null +++ b/src/app/(tabs)/library/artist/[name].tsx @@ -0,0 +1,107 @@ +import { useMemo } from 'react'; +import { Pressable, StyleSheet, View } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { FlashList } from '@shopify/flash-list'; +import { useLocalSearchParams, useRouter } from 'expo-router'; +import { Screen } from '@/components/Screen'; +import { Text } from '@/components/Text'; +import { TrackRow } from '@/components/library/TrackRow'; +import { colors, radius, spacing } from '@/theme'; +import { useLibraryStore } from '@/stores/libraryStore'; +import { usePlayerStore } from '@/stores/playerStore'; +import { playTracks } from '@/audio/playbackController'; +import { dbTrackToTrack } from '@/library/trackAdapter'; + +export default function ArtistScreen() { + const router = useRouter(); + const { name } = useLocalSearchParams<{ name: string }>(); + const allTracks = useLibraryStore((s) => s.tracks); + const currentPath = usePlayerStore((s) => s.currentTrack?.path); + + // Store tracks are ordered artist/album/disc/track, so the filtered slice + // keeps album grouping and track order. + const tracks = useMemo( + () => allTracks.filter((track) => track.artist === name), + [allTracks, name] + ); + + const playFrom = (index: number) => { + void playTracks(tracks.map(dbTrackToTrack), index); + }; + + return ( + + router.back()} hitSlop={8}> + + + Library + + + + + + + {name} + + + {tracks.length} {tracks.length === 1 ? 'track' : 'tracks'} + + + playFrom(0)} accessibilityRole="button"> + + + Play + + + + + String(track.id)} + showsVerticalScrollIndicator={false} + renderItem={({ item, index }) => ( + playFrom(index)} + /> + )} + /> + + ); +} + +const styles = StyleSheet.create({ + back: { + flexDirection: 'row', + alignItems: 'center', + gap: 2, + marginTop: spacing.md, + marginBottom: spacing.md, + alignSelf: 'flex-start', + }, + header: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: spacing.lg, + gap: spacing.lg, + }, + headerMeta: { + flex: 1, + gap: spacing.xs, + }, + playButton: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing.xs, + backgroundColor: colors.accent, + borderRadius: radius.pill, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm, + }, + playLabel: { + color: colors.bgPrimary, + fontWeight: '600', + }, +}); diff --git a/src/app/(tabs)/library/index.tsx b/src/app/(tabs)/library/index.tsx new file mode 100644 index 0000000..5aed1d2 --- /dev/null +++ b/src/app/(tabs)/library/index.tsx @@ -0,0 +1,135 @@ +import { View, StyleSheet } from 'react-native'; +import { FlashList } from '@shopify/flash-list'; +import { useRouter } from 'expo-router'; +import { Screen } from '@/components/Screen'; +import { Text } from '@/components/Text'; +import { ViewModeSwitcher } from '@/components/library/ViewModeSwitcher'; +import { AlbumGridItem } from '@/components/library/AlbumGridItem'; +import { TrackRow } from '@/components/library/TrackRow'; +import { ArtistRow } from '@/components/library/ArtistRow'; +import { FoldersView } from '@/components/library/FoldersView'; +import { ScanProgress } from '@/components/library/ScanProgress'; +import { EmptyLibrary } from '@/components/library/EmptyLibrary'; +import { colors, spacing } from '@/theme'; +import { useLibraryStore } from '@/stores/libraryStore'; +import { usePlayerStore } from '@/stores/playerStore'; +import { playTracks } from '@/audio/playbackController'; +import { dbTrackToTrack } from '@/library/trackAdapter'; + +export default function LibraryScreen() { + const router = useRouter(); + const viewMode = useLibraryStore((s) => s.viewMode); + const setViewMode = useLibraryStore((s) => s.setViewMode); + const albums = useLibraryStore((s) => s.albums); + const artists = useLibraryStore((s) => s.artists); + const tracks = useLibraryStore((s) => s.tracks); + const folders = useLibraryStore((s) => s.folders); + const isScanning = useLibraryStore((s) => s.isScanning); + const scanError = useLibraryStore((s) => s.scanError); + const currentPath = usePlayerStore((s) => s.currentTrack?.path); + + const isEmpty = tracks.length === 0 && folders.length === 0 && !isScanning; + + const playAllFrom = (index: number) => { + void playTracks(tracks.map(dbTrackToTrack), index); + }; + + return ( + + + Library + + + {isEmpty ? ( + + ) : ( + <> + + + + + {scanError ? ( + + Scan problem: {scanError} + + ) : null} + + {viewMode === 'albums' ? ( + album.identity_key} + showsVerticalScrollIndicator={false} + renderItem={({ item }) => ( + + + router.push({ + pathname: '/library/album/[key]', + params: { key: item.identity_key }, + }) + } + /> + + )} + /> + ) : null} + + {viewMode === 'artists' ? ( + artist.artist} + showsVerticalScrollIndicator={false} + renderItem={({ item }) => ( + + router.push({ + pathname: '/library/artist/[name]', + params: { name: item.artist }, + }) + } + /> + )} + /> + ) : null} + + {viewMode === 'tracks' ? ( + String(track.id)} + showsVerticalScrollIndicator={false} + renderItem={({ item, index }) => ( + playAllFrom(index)} + /> + )} + /> + ) : null} + + {viewMode === 'folders' ? : null} + + )} + + ); +} + +const styles = StyleSheet.create({ + heading: { + marginTop: spacing.xl, + marginBottom: spacing.lg, + }, + switcher: { + marginBottom: spacing.md, + }, + error: { + marginBottom: spacing.md, + }, + gridCell: { + flex: 1, + paddingHorizontal: spacing.xs, + }, +}); diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx index 42c1f59..de00333 100644 --- a/src/app/_layout.tsx +++ b/src/app/_layout.tsx @@ -16,6 +16,7 @@ import { JetBrainsMono_500Medium, } from '@expo-google-fonts/jetbrains-mono'; import { usePlaybackSync } from '@/audio/usePlaybackSync'; +import { useLibraryStore } from '@/stores/libraryStore'; import { colors } from '@/theme'; SplashScreen.preventAutoHideAsync(); @@ -42,6 +43,15 @@ export default function RootLayout() { } }, [fontsLoaded]); + // Eager library init: SQLite open + initial reads are tens of ms, and the + // Library tab + playback adapters get data immediately. + useEffect(() => { + useLibraryStore + .getState() + .initialize() + .catch((err) => console.error('[library] init failed', err)); + }, []); + if (!fontsLoaded) return null; return ( diff --git a/src/app/now-playing.tsx b/src/app/now-playing.tsx index e446d28..d518cc6 100644 --- a/src/app/now-playing.tsx +++ b/src/app/now-playing.tsx @@ -6,16 +6,10 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Text } from '@/components/Text'; import { AstraLogo } from '@/components/AstraLogo'; import { FormatBadges } from '@/components/FormatBadge'; -import { colors, fonts, radius, spacing } from '@/theme'; +import { SeekBar } from '@/components/SeekBar'; +import { colors, radius, spacing } from '@/theme'; import { usePlayerStore } from '@/stores/playerStore'; -import { skipToNext, skipToPrevious, togglePlay } from '@/audio/playbackController'; - -function formatTime(seconds: number): string { - const safe = Number.isFinite(seconds) && seconds > 0 ? seconds : 0; - const m = Math.floor(safe / 60); - const s = Math.floor(safe % 60); - return `${m}:${s.toString().padStart(2, '0')}`; -} +import { seekTo, skipToNext, skipToPrevious, togglePlay } from '@/audio/playbackController'; export default function NowPlayingScreen() { const router = useRouter(); @@ -27,7 +21,6 @@ export default function NowPlayingScreen() { const isPlaying = playbackState === 'playing'; const isLoading = playbackState === 'loading'; - const progress = duration > 0 ? Math.min(1, currentTime / duration) : 0; return ( - - - - - - {formatTime(currentTime)} - - - {formatTime(duration)} - - + void seekTo(seconds)} + /> @@ -150,26 +138,7 @@ const styles = StyleSheet.create({ marginTop: spacing.md, }, progressBlock: { - marginTop: spacing.xl, - }, - progressTrack: { - height: 4, - borderRadius: radius.pill, - backgroundColor: colors.glassBorder, - overflow: 'hidden', - }, - progressFill: { - height: 4, - borderRadius: radius.pill, - backgroundColor: colors.accent, - }, - times: { - flexDirection: 'row', - justifyContent: 'space-between', - marginTop: spacing.xs, - }, - time: { - color: colors.textTertiary, + marginTop: spacing.md, }, transport: { marginTop: spacing.xl, diff --git a/src/audio/playbackController.ts b/src/audio/playbackController.ts index 0ad3cc8..d16f5b8 100644 --- a/src/audio/playbackController.ts +++ b/src/audio/playbackController.ts @@ -1,4 +1,5 @@ import TrackPlayer, { isPlaying } from 'react-native-track-player'; +import type { Track } from '@/types/audio'; import { setupPlayer } from './trackPlayer'; import { SAMPLE_TRACKS, toRntpTrack } from './sampleTracks'; @@ -9,22 +10,33 @@ import { SAMPLE_TRACKS, toRntpTrack } from './sampleTracks'; */ /** - * Set up the player and load the demo queue. Setup is deferred to here (a - * user-initiated play) rather than app launch: RNTP starts a foreground - * MediaSession service on setup, and Android only permits starting a foreground - * service while the app is in the foreground. + * Set up the player. Setup is deferred to here (a user-initiated play) rather + * than app launch: RNTP starts a foreground MediaSession service on setup, and + * Android only permits starting a foreground service while the app is in the + * foreground. */ async function ensurePlayerReady(): Promise { await setupPlayer(); +} + +/** Replace the queue with the given tracks and start playing at startIndex. */ +export async function playTracks(tracks: Track[], startIndex = 0): Promise { + if (tracks.length === 0) return; + await ensurePlayerReady(); + await TrackPlayer.setQueue(tracks.map(toRntpTrack)); + if (startIndex > 0) { + await TrackPlayer.skip(startIndex); + } + await TrackPlayer.play(); +} + +/** M0 demo entry point: load the streamed sample queue if nothing is queued. */ +export async function playSample(): Promise { + await ensurePlayerReady(); const queue = await TrackPlayer.getQueue(); if (queue.length === 0) { await TrackPlayer.add(SAMPLE_TRACKS.map(toRntpTrack)); } -} - -/** M0 entry point: ensure the player is ready, then start playback. */ -export async function playSample(): Promise { - await ensurePlayerReady(); await TrackPlayer.play(); } diff --git a/src/components/SeekBar.tsx b/src/components/SeekBar.tsx new file mode 100644 index 0000000..376cb53 --- /dev/null +++ b/src/components/SeekBar.tsx @@ -0,0 +1,162 @@ +import { useRef, useState } from 'react'; +import { View, StyleSheet, type GestureResponderEvent, type LayoutChangeEvent } from 'react-native'; +import { Text } from './Text'; +import { colors, radius, spacing } from '@/theme'; +import { formatDuration } from '@/lib/format'; + +const THUMB_SIZE = 12; + +interface SeekBarProps { + currentTime: number; + duration: number; + onSeek: (seconds: number) => void; + /** Identity of the playing track; a pending seek only applies to its own track. */ + trackKey?: string | number; +} + +const clamp = (fraction: number) => Math.min(1, Math.max(0, fraction)); + +/** + * Tap/drag seek bar with time labels. Plain progress bar for M1 — the + * waveform seek bar port (desktop WaveformSeekBar) replaces the visuals at M3+. + */ +export function SeekBar({ currentTime, duration, onSeek, trackKey }: SeekBarProps) { + const [scrubFraction, setScrubFraction] = useState(null); + const [barWidth, setBarWidth] = useState(0); + // Last released seek. Displayed instead of live progress until playback + // catches up, so the bar doesn't snap back to a stale pre-seek progress + // event; never cleared, just superseded or ignored (pure derivation below). + const [pendingSeek, setPendingSeek] = useState<{ target: number; key?: string | number } | null>( + null + ); + + // Gesture-internal values (only touched inside event handlers). + const widthRef = useRef(0); + const scrubRef = useRef(null); + const grantRef = useRef({ fraction: 0, pageX: 0 }); + + const setScrub = (fraction: number | null) => { + scrubRef.current = fraction; + setScrubFraction(fraction); + }; + + const onLayout = (event: LayoutChangeEvent) => { + widthRef.current = event.nativeEvent.layout.width; + setBarWidth(event.nativeEvent.layout.width); + }; + + const handleGrant = (event: GestureResponderEvent) => { + const fraction = clamp(event.nativeEvent.locationX / Math.max(1, widthRef.current)); + grantRef.current = { fraction, pageX: event.nativeEvent.pageX }; + setScrub(fraction); + }; + + const handleMove = (event: GestureResponderEvent) => { + const delta = (event.nativeEvent.pageX - grantRef.current.pageX) / Math.max(1, widthRef.current); + setScrub(clamp(grantRef.current.fraction + delta)); + }; + + const handleRelease = () => { + const fraction = scrubRef.current ?? grantRef.current.fraction; + const target = fraction * duration; + setPendingSeek({ target, key: trackKey }); + onSeek(target); + setScrub(null); + }; + + // Displayed position: scrub > held seek target > live progress. The held + // target applies only while playback hasn't caught up on the same track. + const holdSeek = + pendingSeek != null && + pendingSeek.key === trackKey && + duration > 0 && + Math.abs(currentTime - pendingSeek.target) >= 1.5; + const liveFraction = duration > 0 ? Math.min(1, currentTime / duration) : 0; + const heldFraction = holdSeek ? clamp(pendingSeek.target / duration) : null; + const fraction = scrubFraction ?? heldFraction ?? liveFraction; + const shownTime = fraction * duration; + + return ( + + duration > 0} + onMoveShouldSetResponder={() => duration > 0} + onResponderTerminationRequest={() => false} + onResponderGrant={handleGrant} + onResponderMove={handleMove} + onResponderRelease={handleRelease} + onResponderTerminate={() => setScrub(null)} + accessibilityRole="adjustable" + accessibilityLabel="Seek" + accessibilityValue={{ + min: 0, + max: Math.round(duration), + now: Math.round(shownTime), + }} + > + + + + + + + + {formatDuration(shownTime)} + + + {formatDuration(duration)} + + + + ); +} + +const styles = StyleSheet.create({ + touchArea: { + justifyContent: 'center', + paddingVertical: spacing.md, // generous touch target around the 4px track + }, + track: { + height: 4, + borderRadius: radius.pill, + backgroundColor: colors.glassBorder, + overflow: 'hidden', + }, + fill: { + height: 4, + borderRadius: radius.pill, + backgroundColor: colors.accent, + }, + thumb: { + position: 'absolute', + width: THUMB_SIZE, + height: THUMB_SIZE, + borderRadius: THUMB_SIZE / 2, + backgroundColor: colors.accent, + }, + thumbActive: { + transform: [{ scale: 1.35 }], + backgroundColor: colors.accentHover, + }, + times: { + flexDirection: 'row', + justifyContent: 'space-between', + }, + time: { + color: colors.textTertiary, + }, + timeActive: { + color: colors.accentText, + }, +}); + +export default SeekBar; diff --git a/src/components/library/AlbumGridItem.tsx b/src/components/library/AlbumGridItem.tsx new file mode 100644 index 0000000..2f6b7e5 --- /dev/null +++ b/src/components/library/AlbumGridItem.tsx @@ -0,0 +1,57 @@ +import { View, Pressable, StyleSheet } from 'react-native'; +import { Image } from 'expo-image'; +import { Text } from '@/components/Text'; +import { AstraLogo } from '@/components/AstraLogo'; +import { colors, radius, spacing } from '@/theme'; +import { artworkUri } from '@/library/artwork'; +import type { Album } from '@/types/library'; + +export function AlbumGridItem({ album, onPress }: { album: Album; onPress: () => void }) { + return ( + + + {album.artwork_hash ? ( + + ) : ( + + )} + + + {album.album} + + + {album.artist} + + + ); +} + +const styles = StyleSheet.create({ + item: { + flex: 1, + marginBottom: spacing.lg, + }, + art: { + aspectRatio: 1, + borderRadius: radius.md, + backgroundColor: colors.bgTertiary, + borderColor: colors.glassBorder, + borderWidth: StyleSheet.hairlineWidth, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + marginBottom: spacing.sm, + }, + artImage: { + width: '100%', + height: '100%', + }, + title: { + fontSize: 14, + }, +}); diff --git a/src/components/library/ArtistRow.tsx b/src/components/library/ArtistRow.tsx new file mode 100644 index 0000000..2af79ed --- /dev/null +++ b/src/components/library/ArtistRow.tsx @@ -0,0 +1,61 @@ +import { View, Pressable, StyleSheet } from 'react-native'; +import { Image } from 'expo-image'; +import { Ionicons } from '@expo/vector-icons'; +import { Text } from '@/components/Text'; +import { colors, radius, spacing } from '@/theme'; +import { artworkUri } from '@/library/artwork'; +import type { Artist } from '@/types/library'; + +export function ArtistRow({ artist, onPress }: { artist: Artist; onPress: () => void }) { + return ( + + + {artist.artwork_hash ? ( + + ) : ( + + )} + + + + {artist.artist} + + + {artist.track_count} {artist.track_count === 1 ? 'track' : 'tracks'} + + + + + ); +} + +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: spacing.sm + 2, + gap: spacing.md, + borderBottomColor: colors.glassBorder, + borderBottomWidth: StyleSheet.hairlineWidth, + }, + art: { + width: 44, + height: 44, + borderRadius: radius.pill, + backgroundColor: colors.bgTertiary, + alignItems: 'center', + justifyContent: 'center', + overflow: 'hidden', + }, + artImage: { + width: '100%', + height: '100%', + }, + meta: { + flex: 1, + }, +}); diff --git a/src/components/library/EmptyLibrary.tsx b/src/components/library/EmptyLibrary.tsx new file mode 100644 index 0000000..1891320 --- /dev/null +++ b/src/components/library/EmptyLibrary.tsx @@ -0,0 +1,58 @@ +import { View, Pressable, StyleSheet } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { Text } from '@/components/Text'; +import { colors, radius, spacing } from '@/theme'; +import { useLibraryStore } from '@/stores/libraryStore'; + +export function EmptyLibrary() { + const addFolder = useLibraryStore((s) => s.addFolder); + + return ( + + + + No music yet + + + Pick a folder on this device and Astra will scan it into your library. + + void addFolder()} accessibilityRole="button"> + + + Add music folder + + + + ); +} + +const styles = StyleSheet.create({ + empty: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + gap: spacing.sm, + paddingBottom: spacing.xxl, + }, + title: { + marginTop: spacing.sm, + }, + body: { + textAlign: 'center', + maxWidth: 280, + }, + cta: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing.sm, + backgroundColor: colors.accent, + borderRadius: radius.pill, + paddingHorizontal: spacing.xl, + paddingVertical: spacing.md, + marginTop: spacing.lg, + }, + ctaLabel: { + color: colors.bgPrimary, + fontWeight: '600', + }, +}); diff --git a/src/components/library/FoldersView.tsx b/src/components/library/FoldersView.tsx new file mode 100644 index 0000000..edcb29f --- /dev/null +++ b/src/components/library/FoldersView.tsx @@ -0,0 +1,121 @@ +import { View, Pressable, StyleSheet, Alert } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { Text } from '@/components/Text'; +import { colors, radius, spacing } from '@/theme'; +import { useLibraryStore } from '@/stores/libraryStore'; +import type { FolderWithCount } from '@/stores/libraryStore'; + +function FolderRow({ folder }: { folder: FolderWithCount }) { + const removeFolder = useLibraryStore((s) => s.removeFolder); + + const confirmRemove = () => { + Alert.alert( + 'Remove folder?', + `"${folder.display_name}" and its ${folder.track_count} tracks will be removed from the library. Files on disk are not touched.`, + [ + { text: 'Cancel', style: 'cancel' }, + { text: 'Remove', style: 'destructive', onPress: () => void removeFolder(folder.id) }, + ] + ); + }; + + return ( + + + + + {folder.display_name} + + + {folder.available + ? `${folder.track_count} ${folder.track_count === 1 ? 'track' : 'tracks'}` + : 'Access lost — remove and add the folder again'} + + + + + + + ); +} + +export function FoldersView() { + const folders = useLibraryStore((s) => s.folders); + const isScanning = useLibraryStore((s) => s.isScanning); + const addFolder = useLibraryStore((s) => s.addFolder); + const rescan = useLibraryStore((s) => s.rescan); + + return ( + + {folders.map((folder) => ( + + ))} + + + void addFolder()} + accessibilityRole="button" + > + + + Add folder + + + {folders.length > 0 ? ( + void rescan()} + accessibilityRole="button" + > + + + Rescan all + + + ) : null} + + + ); +} + +const styles = StyleSheet.create({ + container: { + gap: spacing.xs, + }, + row: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing.md, + paddingVertical: spacing.md, + borderBottomColor: colors.glassBorder, + borderBottomWidth: StyleSheet.hairlineWidth, + }, + meta: { + flex: 1, + }, + actions: { + flexDirection: 'row', + gap: spacing.md, + marginTop: spacing.lg, + }, + action: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing.xs, + borderColor: colors.glassBorder, + borderWidth: StyleSheet.hairlineWidth, + borderRadius: radius.pill, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm, + }, + actionDisabled: { + opacity: 0.4, + }, +}); diff --git a/src/components/library/ScanProgress.tsx b/src/components/library/ScanProgress.tsx new file mode 100644 index 0000000..5fda644 --- /dev/null +++ b/src/components/library/ScanProgress.tsx @@ -0,0 +1,62 @@ +import { View, StyleSheet } from 'react-native'; +import { Text } from '@/components/Text'; +import { colors, spacing } from '@/theme'; +import { useLibraryStore } from '@/stores/libraryStore'; + +/** Thin accent bar + caption shown under the library header while scanning. */ +export function ScanProgress() { + const isScanning = useLibraryStore((s) => s.isScanning); + const progress = useLibraryStore((s) => s.scanProgress); + + if (!isScanning) return null; + + const label = + progress.phase === 'extracting' + ? `Scanning ${progress.folderName ?? ''}… ${progress.processed}/${progress.total}` + : progress.total > 0 + ? `Found ${progress.total} files in ${progress.folderName ?? ''}…` + : `Looking for music${progress.folderName ? ` in ${progress.folderName}` : ''}…`; + + const fraction = + progress.phase === 'extracting' && progress.total > 0 + ? progress.processed / progress.total + : 0; + + return ( + + + {label} + + + 0 ? { width: `${fraction * 100}%` } : styles.fillIndeterminate, + ]} + /> + + + ); +} + +const styles = StyleSheet.create({ + container: { + gap: spacing.xs, + marginBottom: spacing.md, + }, + track: { + height: 2, + backgroundColor: colors.glassBorder, + borderRadius: 1, + overflow: 'hidden', + }, + fill: { + height: 2, + backgroundColor: colors.accent, + }, + fillIndeterminate: { + width: '100%', + opacity: 0.35, + }, +}); diff --git a/src/components/library/TrackRow.tsx b/src/components/library/TrackRow.tsx new file mode 100644 index 0000000..a4efbcc --- /dev/null +++ b/src/components/library/TrackRow.tsx @@ -0,0 +1,91 @@ +import { View, Pressable, StyleSheet } from 'react-native'; +import { Text } from '@/components/Text'; +import { FormatBadges } from '@/components/FormatBadge'; +import { colors, spacing } from '@/theme'; +import { formatDuration } from '@/lib/format'; +import type { DbTrack } from '@/types/library'; + +export function TrackRow({ + track, + onPress, + showArtist = true, + active = false, +}: { + track: DbTrack; + onPress: () => void; + /** Hide on album detail where every row shares the artist. */ + showArtist?: boolean; + active?: boolean; +}) { + return ( + + {track.track_number != null && !showArtist ? ( + + {track.track_number} + + ) : null} + + + + {track.title} + + {showArtist ? ( + + {track.artist} + + ) : null} + + + + + + + {formatDuration(track.duration)} + + + ); +} + +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: spacing.sm + 2, + gap: spacing.md, + borderBottomColor: colors.glassBorder, + borderBottomWidth: StyleSheet.hairlineWidth, + }, + trackNumber: { + width: 24, + fontSize: 12, + color: colors.textTertiary, + textAlign: 'right', + }, + meta: { + flex: 1, + gap: 2, + }, + title: { + fontSize: 15, + }, + titleActive: { + color: colors.accent, + }, + badges: { + marginTop: 2, + }, + duration: { + fontSize: 12, + color: colors.textTertiary, + }, +}); diff --git a/src/components/library/ViewModeSwitcher.tsx b/src/components/library/ViewModeSwitcher.tsx new file mode 100644 index 0000000..0a6f757 --- /dev/null +++ b/src/components/library/ViewModeSwitcher.tsx @@ -0,0 +1,69 @@ +import { View, Pressable, StyleSheet } from 'react-native'; +import { Text } from '@/components/Text'; +import { colors, radius, spacing } from '@/theme'; + +export type LibraryViewMode = 'albums' | 'artists' | 'tracks' | 'folders'; + +const MODES: { key: LibraryViewMode; label: string }[] = [ + { key: 'albums', label: 'Albums' }, + { key: 'artists', label: 'Artists' }, + { key: 'tracks', label: 'Tracks' }, + { key: 'folders', label: 'Folders' }, +]; + +export function ViewModeSwitcher({ + value, + onChange, +}: { + value: LibraryViewMode; + onChange: (mode: LibraryViewMode) => void; +}) { + return ( + + {MODES.map((mode) => { + const active = mode.key === value; + return ( + onChange(mode.key)} + style={[styles.pill, active && styles.pillActive]} + accessibilityRole="button" + accessibilityState={{ selected: active }} + > + + {mode.label} + + + ); + })} + + ); +} + +const styles = StyleSheet.create({ + row: { + flexDirection: 'row', + gap: spacing.sm, + }, + pill: { + backgroundColor: colors.glassBg, + borderColor: colors.glassBorder, + borderWidth: StyleSheet.hairlineWidth, + borderRadius: radius.pill, + paddingHorizontal: spacing.md, + paddingVertical: spacing.xs + 2, + }, + pillActive: { + borderColor: colors.accent, + backgroundColor: 'rgba(56, 189, 248, 0.08)', + }, + label: { + color: colors.textSecondary, + }, + labelActive: { + color: colors.accent, + }, +}); diff --git a/src/db/database.ts b/src/db/database.ts new file mode 100644 index 0000000..c6845b2 --- /dev/null +++ b/src/db/database.ts @@ -0,0 +1,78 @@ +// SQLite access layer — ports the desktop `LibrarySqliteDatabase` wrapper +// (astra/src/main/services/library.ts) onto op-sqlite. Same method surface so +// desktop SQL ports verbatim; methods are async because op-sqlite is async. + +import { open, type DB, type QueryResult, type Scalar, type Transaction } from '@op-engineering/op-sqlite'; +import { migrate } from './schema'; + +export type SqlParams = Scalar[]; + +interface Executor { + execute: (query: string, params?: Scalar[]) => Promise; +} + +export class LibraryDatabase { + constructor( + private readonly executor: Executor, + private readonly db: DB | null = null + ) {} + + async run(sql: string, params: SqlParams = []): Promise<{ changes: number; lastInsertRowid: number }> { + const result = await this.executor.execute(sql, params); + return { changes: result.rowsAffected, lastInsertRowid: result.insertId ?? 0 }; + } + + async exec(sql: string): Promise { + await this.executor.execute(sql); + } + + async get(sql: string, params: SqlParams = []): Promise { + const result = await this.executor.execute(sql, params); + return result.rows[0] as T | undefined; + } + + async all(sql: string, params: SqlParams = []): Promise { + const result = await this.executor.execute(sql, params); + return result.rows as T[]; + } + + /** + * Runs `fn` inside a single transaction; op-sqlite commits on resolve and + * rolls back on throw. The callback receives a LibraryDatabase scoped to the + * transaction — nesting is not supported. + */ + async transaction(fn: (tx: LibraryDatabase) => Promise): Promise { + if (!this.db) { + throw new Error('Nested transactions are not supported'); + } + await this.db.transaction(async (tx: Transaction) => { + await fn(new LibraryDatabase(tx)); + }); + } + + close(): void { + this.db?.close(); + } +} + +let dbPromise: Promise | null = null; + +async function doOpen(): Promise { + const raw = open({ name: 'astra-library.db' }); + const db = new LibraryDatabase(raw, raw); + await db.exec('PRAGMA journal_mode = WAL'); + await db.exec('PRAGMA foreign_keys = ON'); + await migrate(db); + return db; +} + +/** Opens (once) and migrates the library database. */ +export function openLibraryDb(): Promise { + if (!dbPromise) { + dbPromise = doOpen().catch((err) => { + dbPromise = null; // allow retry on genuine failure + throw err; + }); + } + return dbPromise; +} diff --git a/src/db/queries.ts b/src/db/queries.ts new file mode 100644 index 0000000..91c8126 --- /dev/null +++ b/src/db/queries.ts @@ -0,0 +1,212 @@ +// Library queries — SQL ported/adapted from the desktop library service. + +import type { Album, Artist, DbTrack, LibraryFolder } from '@/types/library'; +import type { LibraryDatabase, SqlParams } from './database'; + +/** Row shape the scanner produces for insert/update (id and timestamps are db-managed). */ +export interface TrackUpsert { + path: string; + folder_id: number; + title: string; + artist: string; + album: string; + album_artist: string | null; + album_identity_key: string; + duration: number; + track_number: number | null; + disc_number: number | null; + year: number | null; + genre: string | null; + artwork_hash: string | null; + format: string; + sample_rate: number | null; + bit_depth: number | null; + bitrate: number | null; + channels: number | null; + codec: string | null; + file_name: string; + size: number | null; + mtime: number; +} + +const UPSERT_TRACK_SQL = ` + INSERT INTO tracks ( + path, folder_id, title, artist, album, album_artist, album_identity_key, + duration, track_number, disc_number, year, genre, artwork_hash, format, + sample_rate, bit_depth, bitrate, channels, codec, source_type, + file_name, size, mtime, added_at, modified_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'local', ?, ?, ?, ?, ?) + ON CONFLICT(path) DO UPDATE SET + folder_id = excluded.folder_id, + title = excluded.title, + artist = excluded.artist, + album = excluded.album, + album_artist = excluded.album_artist, + album_identity_key = excluded.album_identity_key, + duration = excluded.duration, + track_number = excluded.track_number, + disc_number = excluded.disc_number, + year = excluded.year, + genre = excluded.genre, + artwork_hash = excluded.artwork_hash, + format = excluded.format, + sample_rate = excluded.sample_rate, + bit_depth = excluded.bit_depth, + bitrate = excluded.bitrate, + channels = excluded.channels, + codec = excluded.codec, + file_name = excluded.file_name, + size = excluded.size, + mtime = excluded.mtime, + modified_at = excluded.modified_at +`; + +export async function upsertTracks(db: LibraryDatabase, rows: TrackUpsert[]): Promise { + if (rows.length === 0) return; + const now = Date.now(); + await db.transaction(async (tx) => { + for (const row of rows) { + await tx.run(UPSERT_TRACK_SQL, [ + row.path, + row.folder_id, + row.title, + row.artist, + row.album, + row.album_artist, + row.album_identity_key, + row.duration, + row.track_number, + row.disc_number, + row.year, + row.genre, + row.artwork_hash, + row.format, + row.sample_rate, + row.bit_depth, + row.bitrate, + row.channels, + row.codec, + row.file_name, + row.size, + row.mtime, + now, + now, + ]); + } + }); +} + +const TRACK_ORDER = 'COALESCE(disc_number, 9999), COALESCE(track_number, 9999), title COLLATE NOCASE'; + +export function getAlbums(db: LibraryDatabase): Promise { + return db.all(` + SELECT album_identity_key AS identity_key, + MAX(album) AS album, + MAX(COALESCE(album_artist, artist)) AS artist, + MAX(year) AS year, + MAX(artwork_hash) AS artwork_hash, + COUNT(*) AS track_count + FROM tracks + GROUP BY album_identity_key + ORDER BY 3 COLLATE NOCASE, 2 COLLATE NOCASE + `); +} + +export function getArtists(db: LibraryDatabase): Promise { + return db.all(` + SELECT artist, + COUNT(*) AS track_count, + MAX(artwork_hash) AS artwork_hash + FROM tracks + GROUP BY artist + ORDER BY artist COLLATE NOCASE + `); +} + +export function getAllTracks(db: LibraryDatabase): Promise { + return db.all(` + SELECT * FROM tracks + ORDER BY artist COLLATE NOCASE, album COLLATE NOCASE, ${TRACK_ORDER} + `); +} + +export function getTracksByAlbumKey(db: LibraryDatabase, identityKey: string): Promise { + return db.all( + `SELECT * FROM tracks WHERE album_identity_key = ? ORDER BY ${TRACK_ORDER}`, + [identityKey] + ); +} + +export function getTracksByArtist(db: LibraryDatabase, artist: string): Promise { + return db.all( + `SELECT * FROM tracks WHERE artist = ? ORDER BY album COLLATE NOCASE, ${TRACK_ORDER}`, + [artist] + ); +} + +export async function getTrackCount(db: LibraryDatabase): Promise { + const row = await db.get<{ count: number }>('SELECT COUNT(*) AS count FROM tracks'); + return row?.count ?? 0; +} + +// --- Folders ----------------------------------------------------------------- + +type FolderRow = Omit; + +export function getFolders(db: LibraryDatabase): Promise { + return db.all('SELECT * FROM folders ORDER BY added_at'); +} + +export async function getFolderTrackCounts(db: LibraryDatabase): Promise> { + const rows = await db.all<{ folder_id: number; count: number }>( + 'SELECT folder_id, COUNT(*) AS count FROM tracks GROUP BY folder_id' + ); + return new Map(rows.map((row) => [row.folder_id, row.count])); +} + +export async function insertFolder( + db: LibraryDatabase, + treeUri: string, + displayName: string +): Promise { + await db.run( + `INSERT INTO folders (tree_uri, display_name, added_at) VALUES (?, ?, ?) + ON CONFLICT(tree_uri) DO UPDATE SET display_name = excluded.display_name`, + [treeUri, displayName, Date.now()] + ); + const row = await db.get('SELECT * FROM folders WHERE tree_uri = ?', [treeUri]); + if (!row) throw new Error('Folder insert failed'); + return row; +} + +export async function deleteFolder(db: LibraryDatabase, folderId: number): Promise { + // ON DELETE CASCADE removes the folder's tracks (foreign_keys is ON per connection). + await db.run('DELETE FROM folders WHERE id = ?', [folderId]); +} + +export async function markFolderScanned(db: LibraryDatabase, folderId: number): Promise { + await db.run('UPDATE folders SET last_scanned_at = ? WHERE id = ?', [Date.now(), folderId]); +} + +// --- Scan support ------------------------------------------------------------ + +export function getFolderSyncRows( + db: LibraryDatabase, + folderId: number +): Promise<{ path: string; size: number | null; mtime: number }[]> { + return db.all('SELECT path, size, mtime FROM tracks WHERE folder_id = ?', [folderId]); +} + +export async function deleteTracksByPaths(db: LibraryDatabase, paths: string[]): Promise { + let deleted = 0; + for (let i = 0; i < paths.length; i += 500) { + const chunk = paths.slice(i, i + 500); + const placeholders = chunk.map(() => '?').join(', '); + const result = await db.run( + `DELETE FROM tracks WHERE path IN (${placeholders})`, + chunk as SqlParams + ); + deleted += result.changes; + } + return deleted; +} diff --git a/src/db/schema.ts b/src/db/schema.ts new file mode 100644 index 0000000..f1c1f37 --- /dev/null +++ b/src/db/schema.ts @@ -0,0 +1,66 @@ +// Library schema — a trimmed port of the desktop schema (astra +// src/main/services/library.ts). v1 covers M1 (local scan + browse); +// playlists arrive as v2 at M2, metadata overrides / lyrics later. + +import type { LibraryDatabase } from './database'; + +export const SCHEMA_VERSION = 1; + +// One statement per entry — op-sqlite executes single statements. +const MIGRATIONS: readonly (readonly string[])[] = [ + // v0 -> v1 + [ + `CREATE TABLE IF NOT EXISTS folders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + tree_uri TEXT UNIQUE NOT NULL, + display_name TEXT NOT NULL, + added_at INTEGER NOT NULL, + last_scanned_at INTEGER + )`, + `CREATE TABLE IF NOT EXISTS tracks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + path TEXT UNIQUE NOT NULL, + folder_id INTEGER NOT NULL REFERENCES folders(id) ON DELETE CASCADE, + title TEXT NOT NULL, + artist TEXT NOT NULL, + album TEXT NOT NULL, + album_artist TEXT, + album_identity_key TEXT NOT NULL, + duration REAL NOT NULL DEFAULT 0, + track_number INTEGER, + disc_number INTEGER, + year INTEGER, + genre TEXT, + artwork_hash TEXT, + format TEXT NOT NULL, + sample_rate INTEGER, + bit_depth INTEGER, + bitrate INTEGER, + channels INTEGER, + codec TEXT, + source_type TEXT NOT NULL DEFAULT 'local', + file_name TEXT NOT NULL, + size INTEGER, + mtime INTEGER NOT NULL DEFAULT 0, + added_at INTEGER NOT NULL, + modified_at INTEGER NOT NULL + )`, + 'CREATE INDEX IF NOT EXISTS idx_tracks_album_identity ON tracks(album_identity_key)', + 'CREATE INDEX IF NOT EXISTS idx_tracks_artist ON tracks(artist)', + 'CREATE INDEX IF NOT EXISTS idx_tracks_folder ON tracks(folder_id)', + ], +]; + +export async function migrate(db: LibraryDatabase): Promise { + const row = await db.get<{ user_version: number }>('PRAGMA user_version'); + const current = row?.user_version ?? 0; + + for (let version = current; version < SCHEMA_VERSION; version++) { + await db.transaction(async (tx) => { + for (const statement of MIGRATIONS[version]) { + await tx.exec(statement); + } + await tx.exec(`PRAGMA user_version = ${version + 1}`); + }); + } +} diff --git a/src/lib/format.ts b/src/lib/format.ts new file mode 100644 index 0000000..9f68817 --- /dev/null +++ b/src/lib/format.ts @@ -0,0 +1,8 @@ +/** 271.3 -> "4:31"; hours roll into minutes ("73:09") like desktop track lists. */ +export function formatDuration(seconds: number): string { + const safe = Number.isFinite(seconds) && seconds > 0 ? seconds : 0; + const total = Math.floor(safe); + const m = Math.floor(total / 60); + const s = total % 60; + return `${m}:${s.toString().padStart(2, '0')}`; +} diff --git a/src/library/artwork.ts b/src/library/artwork.ts new file mode 100644 index 0000000..27f916f --- /dev/null +++ b/src/library/artwork.ts @@ -0,0 +1,13 @@ +// Artwork cache lives in the app's files dir; the native scanner writes +// md5-named files (desktop convention) and tracks store the file name. + +import { AstraLibraryScanner } from '../../modules/astra-library-scanner'; + +let artworkDir: string | null = null; + +export function artworkUri(hash: string): string { + if (!artworkDir) { + artworkDir = AstraLibraryScanner.getArtworkDirPath(); + } + return `file://${artworkDir}/${hash}`; +} diff --git a/src/library/audioExtensions.ts b/src/library/audioExtensions.ts new file mode 100644 index 0000000..73a7798 --- /dev/null +++ b/src/library/audioExtensions.ts @@ -0,0 +1,17 @@ +// Ported from desktop AUDIO_EXTENSIONS (astra src/main/services/library.ts). +// Extensions are passed to the native walk without leading dots. + +export const AUDIO_EXTENSIONS = [ + 'mp3', + 'flac', + 'wav', + 'ogg', + 'aac', + 'm4a', + 'opus', + 'wma', + 'aiff', + 'alac', + 'ape', + 'wv', +]; diff --git a/src/library/scanner.ts b/src/library/scanner.ts new file mode 100644 index 0000000..57f2778 --- /dev/null +++ b/src/library/scanner.ts @@ -0,0 +1,185 @@ +// Scan orchestration: SAF folder pick -> native walk -> diff against DB -> +// native metadata extraction in batches -> batched upserts. Concepts (mtime +// skip, batching, never-abort-on-file-errors) ported from desktop scanFolder. + +import { StorageAccessFramework } from 'expo-file-system/legacy'; +import { AstraLibraryScanner, type ScannedFile } from '../../modules/astra-library-scanner'; +import { openLibraryDb } from '@/db/database'; +import { + deleteFolder, + deleteTracksByPaths, + getFolders, + getFolderSyncRows, + getFolderTrackCounts, + insertFolder, + markFolderScanned, + upsertTracks, + type TrackUpsert, +} from '@/db/queries'; +import type { LibraryFolder } from '@/types/library'; +import { AUDIO_EXTENSIONS } from './audioExtensions'; +import { metadataToUpsertRow } from './trackAdapter'; + +const EXTRACT_BATCH_SIZE = 24; + +export interface ScanProgress { + phase: 'discovering' | 'extracting'; + processed: number; + total: number; + folderName: string; +} + +export interface ScanCallbacks { + onProgress?: (progress: ScanProgress) => void; +} + +export interface ScanResult { + added: number; + updated: number; + removed: number; + errors: number; +} + +function emptyResult(): ScanResult { + return { added: 0, updated: 0, removed: 0, errors: 0 }; +} + +/** "content://…/tree/primary%3AMusic%2FAstraTest" -> "AstraTest" */ +function displayNameFromTreeUri(treeUri: string): string { + const lastSegment = treeUri.split('/').pop() ?? treeUri; + const decoded = decodeURIComponent(lastSegment); + const name = decoded.split(/[/:]/).pop()?.trim(); + return name || 'Music folder'; +} + +/** Folder rows joined with current permission state and track counts. */ +export async function loadFolders(): Promise<(LibraryFolder & { track_count: number })[]> { + const db = await openLibraryDb(); + const [rows, counts] = await Promise.all([getFolders(db), getFolderTrackCounts(db)]); + const persisted = new Set(AstraLibraryScanner.getPersistedTreeUris()); + return rows.map((row) => ({ + ...row, + available: persisted.has(row.tree_uri), + track_count: counts.get(row.id) ?? 0, + })); +} + +/** + * System folder picker -> persist grant -> folder row -> scan. + * Returns null if the user cancelled the picker. + */ +export async function addFolderViaPicker(callbacks?: ScanCallbacks): Promise { + const permission = await StorageAccessFramework.requestDirectoryPermissionsAsync(); + if (!permission.granted) return null; + + const treeUri = permission.directoryUri; + await AstraLibraryScanner.takePersistableUriPermission(treeUri); + + const db = await openLibraryDb(); + const row = await insertFolder(db, treeUri, displayNameFromTreeUri(treeUri)); + return scanFolder({ ...row, available: true }, { callbacks }); +} + +export async function scanFolder( + folder: Omit & { available?: boolean }, + opts: { mode?: 'incremental' | 'full'; callbacks?: ScanCallbacks } = {} +): Promise { + const { mode = 'incremental', callbacks } = opts; + const db = await openLibraryDb(); + const result = emptyResult(); + + // Native discovery runs as one promise; forward its progress events. + const subscription = AstraLibraryScanner.addListener('onScanProgress', (event) => { + callbacks?.onProgress?.({ + phase: 'discovering', + processed: 0, + total: event.found, + folderName: folder.display_name, + }); + }); + callbacks?.onProgress?.({ phase: 'discovering', processed: 0, total: 0, folderName: folder.display_name }); + + let files: ScannedFile[]; + let covers: Record; + try { + const listing = await AstraLibraryScanner.listAudioFiles(folder.tree_uri, AUDIO_EXTENSIONS); + files = listing.files; + covers = listing.covers; + } finally { + subscription.remove(); + } + + // Diff against what the DB knows about this folder. + const existingRows = await getFolderSyncRows(db, folder.id); + const existingByPath = new Map(existingRows.map((row) => [row.path, row])); + const seenPaths = new Set(files.map((file) => file.uri)); + + const toDelete = existingRows.filter((row) => !seenPaths.has(row.path)).map((row) => row.path); + const toExtract = files.filter((file) => { + const existing = existingByPath.get(file.uri); + if (!existing || mode === 'full') return true; + return existing.mtime !== file.lastModified || existing.size !== file.size; + }); + + result.removed = await deleteTracksByPaths(db, toDelete); + + let processed = 0; + for (let i = 0; i < toExtract.length; i += EXTRACT_BATCH_SIZE) { + const batch = toExtract.slice(i, i + EXTRACT_BATCH_SIZE); + const extracted = await AstraLibraryScanner.extractMetadata( + batch.map((file) => ({ uri: file.uri, coverUri: covers[file.parentUri] ?? null })) + ); + const metaByUri = new Map(extracted.map((meta) => [meta.uri, meta])); + + const rows: TrackUpsert[] = []; + for (const file of batch) { + const meta = metaByUri.get(file.uri); + if (!meta?.ok) { + result.errors += 1; + continue; + } + rows.push(metadataToUpsertRow(meta, file, folder.id)); + if (existingByPath.has(file.uri)) { + result.updated += 1; + } else { + result.added += 1; + } + } + await upsertTracks(db, rows); + + processed += batch.length; + callbacks?.onProgress?.({ + phase: 'extracting', + processed, + total: toExtract.length, + folderName: folder.display_name, + }); + } + + await markFolderScanned(db, folder.id); + return result; +} + +/** Rescans every folder whose permission grant is still alive. */ +export async function rescanAll( + opts: { mode?: 'incremental' | 'full'; callbacks?: ScanCallbacks } = {} +): Promise { + const folders = await loadFolders(); + const total = emptyResult(); + for (const folder of folders) { + if (!folder.available) continue; + const result = await scanFolder(folder, opts); + total.added += result.added; + total.updated += result.updated; + total.removed += result.removed; + total.errors += result.errors; + } + return total; +} + +/** Explicit user removal: drop the folder (tracks CASCADE) and release the grant. */ +export async function removeFolder(folder: Pick): Promise { + const db = await openLibraryDb(); + await deleteFolder(db, folder.id); + await AstraLibraryScanner.releasePersistedUriPermission(folder.tree_uri); +} diff --git a/src/library/trackAdapter.ts b/src/library/trackAdapter.ts new file mode 100644 index 0000000..440b987 --- /dev/null +++ b/src/library/trackAdapter.ts @@ -0,0 +1,128 @@ +// Adapters between the native scanner output, the SQLite row shape, and the +// app-level Track model the player consumes. + +import type { Track } from '@/types/audio'; +import type { DbTrack } from '@/types/library'; +import type { TrackUpsert } from '@/db/queries'; +import type { ExtractedMetadata, ScannedFile } from '../../modules/astra-library-scanner'; +import { artworkUri } from './artwork'; + +const UNKNOWN_ARTIST = 'Unknown Artist'; +const UNKNOWN_ALBUM = 'Unknown Album'; + +// Ports desktop normalizeDisplay/normalizeKey (library.ts:1023). +function normalizeKey(value: string): string { + return value.replace(/\s+/g, ' ').trim().toLocaleLowerCase(); +} + +// M1-simple album identity: normalized "|". +// Stored per track so getAlbums is a plain GROUP BY; the desktop compilation +// heuristic can land later by recomputing this column. +export function buildAlbumIdentityKey( + albumArtist: string | null, + artist: string, + album: string +): string { + const artistKey = normalizeKey(albumArtist || artist) || 'unknown artist'; + const albumKey = normalizeKey(album) || 'unknown album'; + return `${artistKey}|${albumKey}`; +} + +const CODEC_BY_MIME: Record = { + 'audio/flac': 'flac', + 'audio/mpeg': 'mp3', + 'audio/mpeg-l2': 'mp2', + 'audio/mp4a-latm': 'aac', + 'audio/aac': 'aac', + 'audio/alac': 'alac', + 'audio/opus': 'opus', + 'audio/vorbis': 'vorbis', + 'audio/raw': 'pcm', + 'audio/ac3': 'ac3', + 'audio/eac3': 'eac3', +}; + +function codecFromMime( + trackMime: string | null | undefined, + containerMime: string | null | undefined +): string | null { + // Some framework extractors (e.g. FLAC) expose the decoded track as + // audio/raw; the container mime identifies the real codec there. + const mime = trackMime === 'audio/raw' && containerMime ? containerMime : trackMime; + if (!mime) return null; + return CODEC_BY_MIME[mime] ?? mime.replace(/^audio\//, ''); +} + +function fileExtension(name: string): string { + const dot = name.lastIndexOf('.'); + return dot >= 0 ? name.slice(dot + 1) : ''; +} + +function cleanTag(value: string | null | undefined): string | null { + const trimmed = value?.trim(); + return trimmed ? trimmed : null; +} + +export function metadataToUpsertRow( + meta: ExtractedMetadata, + file: ScannedFile, + folderId: number +): TrackUpsert { + const extension = fileExtension(file.name); + const title = cleanTag(meta.title) ?? file.name.slice(0, file.name.length - (extension ? extension.length + 1 : 0)); + const artist = cleanTag(meta.artist) ?? UNKNOWN_ARTIST; + const album = cleanTag(meta.album) ?? UNKNOWN_ALBUM; + const albumArtist = cleanTag(meta.albumArtist); + + return { + path: file.uri, + folder_id: folderId, + title, + artist, + album, + album_artist: albumArtist, + album_identity_key: buildAlbumIdentityKey(albumArtist, artist, album), + duration: meta.durationMs != null ? meta.durationMs / 1000 : 0, + track_number: meta.trackNumber ?? null, + disc_number: meta.discNumber ?? null, + year: meta.year ?? null, + genre: cleanTag(meta.genre), + artwork_hash: meta.artworkHash ?? null, + format: extension ? extension.toUpperCase() : 'UNKNOWN', + sample_rate: meta.sampleRate ?? null, + bit_depth: meta.bitsPerSample ?? null, + bitrate: meta.bitrate ?? null, + channels: meta.channels ?? null, + codec: codecFromMime(meta.codecMime, meta.mimeType), + file_name: file.name, + size: file.size, + mtime: file.lastModified, + }; +} + +export function dbTrackToTrack(track: DbTrack): Track { + return { + id: String(track.id), + path: track.path, + origin: 'library', + title: track.title, + artist: track.artist, + album: track.album, + albumArtist: track.album_artist ?? undefined, + albumIdentityKey: track.album_identity_key, + duration: track.duration, + trackNumber: track.track_number ?? undefined, + discNumber: track.disc_number ?? undefined, + year: track.year ?? undefined, + genre: track.genre ?? undefined, + artworkData: track.artwork_hash ? artworkUri(track.artwork_hash) : undefined, + artworkHash: track.artwork_hash ?? undefined, + format: track.format, + sampleRate: track.sample_rate ?? undefined, + bitDepth: track.bit_depth ?? undefined, + bitrate: track.bitrate ?? undefined, + channels: track.channels ?? undefined, + codec: track.codec ?? undefined, + sourceType: track.source_type, + }; +} diff --git a/src/stores/libraryStore.ts b/src/stores/libraryStore.ts index 53b2985..2f87e38 100644 --- a/src/stores/libraryStore.ts +++ b/src/stores/libraryStore.ts @@ -1,30 +1,121 @@ import { create } from 'zustand'; -import type { Album, Artist, DbTrack } from '@/types/library'; +import type { Album, Artist, DbTrack, LibraryFolder } from '@/types/library'; +import { openLibraryDb } from '@/db/database'; +import { getAlbums, getAllTracks, getArtists, getTrackCount } from '@/db/queries'; +import { + addFolderViaPicker, + loadFolders, + removeFolder as scannerRemoveFolder, + rescanAll, + type ScanProgress, + type ScanResult, +} from '@/library/scanner'; /** - * Library state — minimal M0 stub. Real on-device scanning + SQLite (op-sqlite) - * land at M1; the shapes here mirror desktop `libraryStore` so that work slots in. + * Library state — SQLite is the source of truth (no persist middleware); + * this store mirrors it in memory for the UI plus scan/UI state. */ type ViewMode = 'tracks' | 'albums' | 'artists' | 'folders'; +export type FolderWithCount = LibraryFolder & { track_count: number }; + +interface ScanProgressState { + phase: 'idle' | 'discovering' | 'extracting'; + processed: number; + total: number; + folderName?: string; +} + +const IDLE_PROGRESS: ScanProgressState = { phase: 'idle', processed: 0, total: 0 }; + interface LibraryStore { + initialized: boolean; tracks: DbTrack[]; albums: Album[]; artists: Artist[]; + folders: FolderWithCount[]; totalTrackCount: number; viewMode: ViewMode; isScanning: boolean; + scanProgress: ScanProgressState; + scanError: string | null; + initialize: () => Promise; + refresh: () => Promise; setViewMode: (mode: ViewMode) => void; + addFolder: () => Promise; + removeFolder: (folderId: number) => Promise; + rescan: () => Promise; } -export const useLibraryStore = create((set) => ({ - tracks: [], - albums: [], - artists: [], - totalTrackCount: 0, - viewMode: 'albums', - isScanning: false, +let initPromise: Promise | null = null; - setViewMode: (viewMode) => set({ viewMode }), -})); +export const useLibraryStore = create((set, get) => { + const onProgress = (progress: ScanProgress) => set({ scanProgress: progress }); + + /** Shared scan wrapper: progress/error state + refresh, scans never overlap. */ + const runScan = async (scan: () => Promise) => { + if (get().isScanning) return; + set({ isScanning: true, scanError: null, scanProgress: { ...IDLE_PROGRESS } }); + try { + await scan(); + } catch (err) { + set({ scanError: err instanceof Error ? err.message : String(err) }); + } finally { + await get().refresh(); + set({ isScanning: false, scanProgress: { ...IDLE_PROGRESS } }); + } + }; + + return { + initialized: false, + tracks: [], + albums: [], + artists: [], + folders: [], + totalTrackCount: 0, + viewMode: 'albums', + isScanning: false, + scanProgress: { ...IDLE_PROGRESS }, + scanError: null, + + initialize: () => { + if (!initPromise) { + initPromise = (async () => { + await openLibraryDb(); + await get().refresh(); + set({ initialized: true }); + })().catch((err) => { + initPromise = null; // allow retry on genuine failure + throw err; + }); + } + return initPromise; + }, + + refresh: async () => { + const db = await openLibraryDb(); + const [tracks, albums, artists, folders, totalTrackCount] = await Promise.all([ + getAllTracks(db), + getAlbums(db), + getArtists(db), + loadFolders(), + getTrackCount(db), + ]); + set({ tracks, albums, artists, folders, totalTrackCount }); + }, + + setViewMode: (viewMode) => set({ viewMode }), + + addFolder: () => runScan(() => addFolderViaPicker({ onProgress })), + + removeFolder: async (folderId) => { + const folder = get().folders.find((entry) => entry.id === folderId); + if (!folder) return; + await scannerRemoveFolder(folder); + await get().refresh(); + }, + + rescan: () => runScan(() => rescanAll({ callbacks: { onProgress } })), + }; +}); diff --git a/src/theme/colors.ts b/src/theme/colors.ts index 06e3dfd..8079170 100644 --- a/src/theme/colors.ts +++ b/src/theme/colors.ts @@ -18,6 +18,9 @@ export const colors = { textSecondary: 'rgba(255, 255, 255, 0.6)', textTertiary: 'rgba(255, 255, 255, 0.4)', + // Warning amber (desktop .graph-meta-chip-warning) + warning: '#f3d27d', + // Cyan accent accent: '#38bdf8', accentHover: '#7dd3fc', diff --git a/src/types/library.ts b/src/types/library.ts index 8dcad15..c21cc61 100644 --- a/src/types/library.ts +++ b/src/types/library.ts @@ -5,11 +5,13 @@ export type TrackSourceType = 'local' | 'subsonic' | 'jellyfin'; export interface DbTrack { id: number; - path: string; + path: string; // SAF document content:// URI for local tracks + folder_id: number; title: string; artist: string; album: string; album_artist: string | null; + album_identity_key: string; duration: number; track_number: number | null; disc_number: number | null; @@ -23,7 +25,21 @@ export interface DbTrack { channels: number | null; codec: string | null; source_type: TrackSourceType; + file_name: string; + size: number | null; + mtime: number; added_at: number; + modified_at: number; +} + +export interface LibraryFolder { + id: number; + tree_uri: string; + display_name: string; + added_at: number; + last_scanned_at: number | null; + /** Computed against persisted URI permissions at load time — not stored. */ + available: boolean; } export interface Album {