WIP: hi-res support
This commit is contained in:
parent
3e212a7e5b
commit
1e7595c159
7 changed files with 658 additions and 48 deletions
|
|
@ -1106,6 +1106,7 @@
|
|||
<span class="description">Quality for streaming playback</span>
|
||||
</div>
|
||||
<select id="streaming-quality-setting">
|
||||
<option value="HI_RES_LOSSLESS">Hi-Res FLAC (24-bit)</option>
|
||||
<option value="LOSSLESS">FLAC (Lossless)</option>
|
||||
<option value="HIGH">AAC 320kbps</option>
|
||||
<option value="LOW">AAC 96kbps</option>
|
||||
|
|
@ -1117,6 +1118,7 @@
|
|||
<span class="description">Quality for track downloads</span>
|
||||
</div>
|
||||
<select id="download-quality-setting">
|
||||
<option value="HI_RES_LOSSLESS">Hi-Res FLAC (24-bit)</option>
|
||||
<option value="LOSSLESS">FLAC (Lossless)</option>
|
||||
<option value="HIGH">AAC 320kbps</option>
|
||||
<option value="LOW">AAC 96kbps</option>
|
||||
|
|
|
|||
93
js/api.js
93
js/api.js
|
|
@ -2,6 +2,7 @@
|
|||
import { RATE_LIMIT_ERROR_MESSAGE, deriveTrackQuality, delay } from './utils.js';
|
||||
import { APICache } from './cache.js';
|
||||
import { addMetadataToAudio } from './metadata.js';
|
||||
import { DashDownloader } from './dash-downloader.js';
|
||||
|
||||
export const DASH_MANIFEST_UNAVAILABLE_CODE = 'DASH_MANIFEST_UNAVAILABLE';
|
||||
|
||||
|
|
@ -215,6 +216,12 @@ export class LosslessAPI {
|
|||
try {
|
||||
const decoded = atob(manifest);
|
||||
|
||||
// Check if it's a DASH manifest (XML)
|
||||
if (decoded.includes('<MPD')) {
|
||||
const blob = new Blob([decoded], { type: 'application/dash+xml' });
|
||||
return URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(decoded);
|
||||
if (parsed?.urls?.[0]) {
|
||||
|
|
@ -883,6 +890,7 @@ export class LosslessAPI {
|
|||
try {
|
||||
const lookup = await this.getTrack(id, quality);
|
||||
let streamUrl;
|
||||
let blob;
|
||||
|
||||
if (lookup.originalTrackUrl) {
|
||||
streamUrl = lookup.originalTrackUrl;
|
||||
|
|
@ -893,51 +901,70 @@ export class LosslessAPI {
|
|||
}
|
||||
}
|
||||
|
||||
const response = await fetch(streamUrl, {
|
||||
cache: 'no-store',
|
||||
signal: options.signal,
|
||||
});
|
||||
// Handle DASH streams (blob URLs)
|
||||
if (streamUrl.startsWith('blob:')) {
|
||||
try {
|
||||
const downloader = new DashDownloader();
|
||||
blob = await downloader.downloadDashStream(streamUrl, {
|
||||
signal: options.signal,
|
||||
onProgress: options.onProgress
|
||||
});
|
||||
} catch (dashError) {
|
||||
console.error('DASH download failed:', dashError);
|
||||
// Fallback to LOSSLESS if DASH fails
|
||||
if (quality !== 'LOSSLESS') {
|
||||
console.warn('Falling back to LOSSLESS (16-bit) download.');
|
||||
return this.downloadTrack(id, 'LOSSLESS', filename, options);
|
||||
}
|
||||
throw dashError;
|
||||
}
|
||||
} else {
|
||||
const response = await fetch(streamUrl, {
|
||||
cache: 'no-store',
|
||||
signal: options.signal,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Fetch failed: ${response.status}`);
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(`Fetch failed: ${response.status}`);
|
||||
}
|
||||
|
||||
// ... (standard handling for Content-Length and body reader)
|
||||
const contentLength = response.headers.get('Content-Length');
|
||||
const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
|
||||
|
||||
const contentLength = response.headers.get('Content-Length');
|
||||
const totalBytes = contentLength ? parseInt(contentLength, 10) : 0;
|
||||
let receivedBytes = 0;
|
||||
|
||||
let receivedBytes = 0;
|
||||
let blob;
|
||||
if (response.body && onProgress) {
|
||||
const reader = response.body.getReader();
|
||||
const chunks = [];
|
||||
|
||||
if (response.body && onProgress) {
|
||||
const reader = response.body.getReader();
|
||||
const chunks = [];
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
if (value) {
|
||||
chunks.push(value);
|
||||
receivedBytes += value.byteLength;
|
||||
|
||||
if (value) {
|
||||
chunks.push(value);
|
||||
receivedBytes += value.byteLength;
|
||||
onProgress({
|
||||
stage: 'downloading',
|
||||
receivedBytes,
|
||||
totalBytes: totalBytes || undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
blob = new Blob(chunks, { type: response.headers.get('Content-Type') || 'audio/flac' });
|
||||
} else {
|
||||
blob = await response.blob();
|
||||
if (onProgress) {
|
||||
onProgress({
|
||||
stage: 'downloading',
|
||||
receivedBytes,
|
||||
totalBytes: totalBytes || undefined,
|
||||
receivedBytes: blob.size,
|
||||
totalBytes: blob.size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
blob = new Blob(chunks, { type: response.headers.get('Content-Type') || 'audio/flac' });
|
||||
} else {
|
||||
blob = await response.blob();
|
||||
if (onProgress) {
|
||||
onProgress({
|
||||
stage: 'downloading',
|
||||
receivedBytes: blob.size,
|
||||
totalBytes: blob.size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add metadata if track information is provided
|
||||
|
|
|
|||
200
js/dash-downloader.js
Normal file
200
js/dash-downloader.js
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
export class DashDownloader {
|
||||
constructor() {}
|
||||
|
||||
async downloadDashStream(manifestBlobUrl, options = {}) {
|
||||
const { onProgress, signal } = options;
|
||||
|
||||
// 1. Fetch and Parse Manifest
|
||||
const response = await fetch(manifestBlobUrl);
|
||||
const manifestText = await response.text();
|
||||
|
||||
const manifest = this.parseManifest(manifestText);
|
||||
if (!manifest) {
|
||||
throw new Error("Failed to parse DASH manifest");
|
||||
}
|
||||
|
||||
// 2. Generate URLs
|
||||
const urls = this.generateSegmentUrls(manifest);
|
||||
|
||||
// 3. Download Segments
|
||||
const chunks = [];
|
||||
let downloadedBytes = 0;
|
||||
// Estimate total size? Hard to know exactly without Content-Length of each.
|
||||
// We can just track progress by segment count.
|
||||
const totalSegments = urls.length;
|
||||
|
||||
for (let i = 0; i < urls.length; i++) {
|
||||
if (signal?.aborted) throw new Error('AbortError');
|
||||
|
||||
const url = urls[i];
|
||||
const segmentResponse = await fetch(url, { signal });
|
||||
|
||||
if (!segmentResponse.ok) {
|
||||
// Retry once?
|
||||
console.warn(`Failed to fetch segment ${i}, retrying...`);
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
const retryResponse = await fetch(url, { signal });
|
||||
if (!retryResponse.ok) throw new Error(`Failed to fetch segment ${i}: ${retryResponse.status}`);
|
||||
const chunk = await retryResponse.arrayBuffer();
|
||||
chunks.push(chunk);
|
||||
downloadedBytes += chunk.byteLength;
|
||||
} else {
|
||||
const chunk = await segmentResponse.arrayBuffer();
|
||||
chunks.push(chunk);
|
||||
downloadedBytes += chunk.byteLength;
|
||||
}
|
||||
|
||||
if (onProgress) {
|
||||
onProgress({
|
||||
stage: 'downloading',
|
||||
receivedBytes: downloadedBytes, // accurate byte count
|
||||
totalBytes: undefined, // Unknown total
|
||||
currentSegment: i + 1,
|
||||
totalSegments: totalSegments
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Concatenate
|
||||
return new Blob(chunks, { type: 'audio/mp4' });
|
||||
}
|
||||
|
||||
parseManifest(manifestText) {
|
||||
const parser = new DOMParser();
|
||||
const xml = parser.parseFromString(manifestText, "text/xml");
|
||||
|
||||
const mpd = xml.querySelector("MPD");
|
||||
if (!mpd) throw new Error("Invalid DASH manifest: No MPD tag");
|
||||
|
||||
const period = mpd.querySelector("Period");
|
||||
if (!period) throw new Error("Invalid DASH manifest: No Period tag");
|
||||
|
||||
// Prefer highest bandwidth audio adaptation set
|
||||
const adaptationSets = Array.from(period.querySelectorAll("AdaptationSet"));
|
||||
let audioSet = adaptationSets.find(as => as.getAttribute("mimeType")?.startsWith("audio"));
|
||||
|
||||
// Fallback: look for any adaptation set if mimeType is missing (rare)
|
||||
if (!audioSet && adaptationSets.length > 0) audioSet = adaptationSets[0];
|
||||
if (!audioSet) throw new Error("No AdaptationSet found");
|
||||
|
||||
// Find Representation
|
||||
// Get all representations and sort by bandwidth descending
|
||||
const representations = Array.from(audioSet.querySelectorAll("Representation"))
|
||||
.sort((a, b) => {
|
||||
const bwA = parseInt(a.getAttribute("bandwidth") || "0");
|
||||
const bwB = parseInt(b.getAttribute("bandwidth") || "0");
|
||||
return bwB - bwA;
|
||||
});
|
||||
|
||||
if (representations.length === 0) throw new Error("No Representation found");
|
||||
const rep = representations[0];
|
||||
const repId = rep.getAttribute("id");
|
||||
|
||||
// Find SegmentTemplate
|
||||
// Can be in Representation or AdaptationSet
|
||||
const segmentTemplate = rep.querySelector("SegmentTemplate") || audioSet.querySelector("SegmentTemplate");
|
||||
if (!segmentTemplate) throw new Error("No SegmentTemplate found");
|
||||
|
||||
const initialization = segmentTemplate.getAttribute("initialization");
|
||||
const media = segmentTemplate.getAttribute("media");
|
||||
const startNumber = parseInt(segmentTemplate.getAttribute("startNumber") || "1", 10);
|
||||
|
||||
// BaseURL
|
||||
// Can be at MPD, Period, AdaptationSet, or Representation level.
|
||||
// We strictly need to find the "deepest" one or combine them?
|
||||
// Usually simpler manifests have it at one level.
|
||||
// Let's resolve closest BaseURL.
|
||||
const baseUrlTag = rep.querySelector("BaseURL") ||
|
||||
audioSet.querySelector("BaseURL") ||
|
||||
period.querySelector("BaseURL") ||
|
||||
mpd.querySelector("BaseURL");
|
||||
const baseUrl = baseUrlTag ? baseUrlTag.textContent.trim() : "";
|
||||
|
||||
// SegmentTimeline
|
||||
const segmentTimeline = segmentTemplate.querySelector("SegmentTimeline");
|
||||
const segments = [];
|
||||
|
||||
if (segmentTimeline) {
|
||||
const sElements = segmentTimeline.querySelectorAll("S");
|
||||
let currentTime = 0;
|
||||
let currentNumber = startNumber;
|
||||
|
||||
sElements.forEach(s => {
|
||||
// t is optional, defaults to previous end
|
||||
const tAttr = s.getAttribute("t");
|
||||
if (tAttr) currentTime = parseInt(tAttr, 10);
|
||||
|
||||
const d = parseInt(s.getAttribute("d"), 10);
|
||||
const r = parseInt(s.getAttribute("r") || "0", 10);
|
||||
|
||||
// Initial segment
|
||||
segments.push({ number: currentNumber, time: currentTime });
|
||||
currentTime += d;
|
||||
currentNumber++;
|
||||
|
||||
// Repeats
|
||||
// r is the number of REPEATS (so total occurrences = 1 + r)
|
||||
// If r is negative, it refers to open-ended? (Usually not in static manifests)
|
||||
for (let i = 0; i < r; i++) {
|
||||
segments.push({ number: currentNumber, time: currentTime });
|
||||
currentTime += d;
|
||||
currentNumber++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
baseUrl,
|
||||
initialization,
|
||||
media,
|
||||
segments,
|
||||
repId
|
||||
};
|
||||
}
|
||||
|
||||
generateSegmentUrls(manifest) {
|
||||
const { baseUrl, initialization, media, segments, repId } = manifest;
|
||||
const urls = [];
|
||||
|
||||
// Helper to resolve template strings
|
||||
const resolveTemplate = (template, number, time) => {
|
||||
return template
|
||||
.replace(/\$RepresentationID\$/g, repId)
|
||||
.replace(/\$Number(?:%0([0-9]+)d)?\$/g, (match, width) => {
|
||||
if (width) {
|
||||
return number.toString().padStart(parseInt(width), '0');
|
||||
}
|
||||
return number;
|
||||
})
|
||||
.replace(/\$Time(?:%0([0-9]+)d)?\$/g, (match, width) => {
|
||||
if (width) {
|
||||
return time.toString().padStart(parseInt(width), '0');
|
||||
}
|
||||
return time;
|
||||
});
|
||||
};
|
||||
|
||||
// Helper to join paths handling slashes
|
||||
const joinPath = (base, part) => {
|
||||
if (!base) return part;
|
||||
if (part.startsWith('http')) return part; // Absolute path
|
||||
return base.endsWith('/') ? base + part : base + '/' + part;
|
||||
};
|
||||
|
||||
// 1. Initialization Segment
|
||||
if (initialization) {
|
||||
const initPath = resolveTemplate(initialization, 0, 0); // Init often doesn't use Number/Time but just in case
|
||||
urls.push(joinPath(baseUrl, initPath));
|
||||
}
|
||||
|
||||
// 2. Media Segments
|
||||
if (segments && segments.length > 0) {
|
||||
segments.forEach(seg => {
|
||||
const path = resolveTemplate(media, seg.number, seg.time);
|
||||
urls.push(joinPath(baseUrl, path));
|
||||
});
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from './utils.js';
|
||||
import { lyricsSettings } from './storage.js';
|
||||
import { addMetadataToAudio } from './metadata.js';
|
||||
import { DashDownloader } from './dash-downloader.js';
|
||||
|
||||
const downloadTasks = new Map();
|
||||
const bulkDownloadTasks = new Map();
|
||||
|
|
@ -223,13 +224,28 @@ async function downloadTrackBlob(track, quality, api, lyricsManager = null, sign
|
|||
}
|
||||
}
|
||||
|
||||
const response = await fetch(streamUrl, { signal });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch track: ${response.status}`);
|
||||
// Handle DASH streams (blob URLs)
|
||||
if (streamUrl.startsWith('blob:')) {
|
||||
try {
|
||||
const downloader = new DashDownloader();
|
||||
blob = await downloader.downloadDashStream(streamUrl, { signal });
|
||||
} catch (dashError) {
|
||||
console.error('DASH download failed:', dashError);
|
||||
// Fallback
|
||||
if (quality !== 'LOSSLESS') {
|
||||
console.warn('Falling back to LOSSLESS (16-bit) download.');
|
||||
return downloadTrackBlob(track, 'LOSSLESS', api, lyricsManager, signal);
|
||||
}
|
||||
throw dashError;
|
||||
}
|
||||
} else {
|
||||
const response = await fetch(streamUrl, { signal });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch track: ${response.status}`);
|
||||
}
|
||||
blob = await response.blob();
|
||||
}
|
||||
|
||||
let blob = await response.blob();
|
||||
|
||||
// Add metadata to the blob
|
||||
blob = await addMetadataToAudio(blob, enrichedTrack, api, quality);
|
||||
|
||||
|
|
|
|||
52
js/player.js
52
js/player.js
|
|
@ -1,4 +1,5 @@
|
|||
//js/player.js
|
||||
import { MediaPlayer } from 'dashjs';
|
||||
import { REPEAT_MODE, formatTime, getTrackArtists, getTrackTitle, getTrackArtistsHTML } from './utils.js';
|
||||
import { queueManager, replayGainSettings } from './storage.js';
|
||||
|
||||
|
|
@ -24,6 +25,17 @@ export class Player {
|
|||
this.sleepTimerEndTime = null;
|
||||
this.sleepTimerInterval = null;
|
||||
|
||||
// Initialize dash.js player
|
||||
this.dashPlayer = MediaPlayer().create();
|
||||
this.dashPlayer.updateSettings({
|
||||
streaming: {
|
||||
buffer: {
|
||||
fastSwitchEnabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
this.dashInitialized = false;
|
||||
|
||||
this.loadQueueState();
|
||||
this.setupMediaSession();
|
||||
|
||||
|
|
@ -208,10 +220,13 @@ export class Player {
|
|||
|
||||
this.preloadCache.set(track.id, streamUrl);
|
||||
// Warm connection/cache
|
||||
fetch(streamUrl, { method: 'HEAD', signal: this.preloadAbortController.signal }).catch(() => {});
|
||||
// For Blob URLs (DASH), this head request is not needed and can cause errors.
|
||||
if (!streamUrl.startsWith('blob:')) {
|
||||
fetch(streamUrl, { method: 'HEAD', signal: this.preloadAbortController.signal }).catch(() => {});
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.name !== 'AbortError') {
|
||||
console.debug('Failed to get stream URL for preload:', trackTitle);
|
||||
// console.debug('Failed to get stream URL for preload:', trackTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -256,9 +271,16 @@ export class Player {
|
|||
let streamUrl;
|
||||
|
||||
if (track.isLocal && track.file) {
|
||||
this.dashPlayer.reset(); // Ensure dash is off
|
||||
streamUrl = URL.createObjectURL(track.file);
|
||||
this.currentRgValues = null; // No replaygain for local files yet
|
||||
this.applyReplayGain();
|
||||
|
||||
this.audio.src = streamUrl;
|
||||
if (startTime > 0) {
|
||||
this.audio.currentTime = startTime;
|
||||
}
|
||||
await this.audio.play();
|
||||
} else {
|
||||
// Get track data for ReplayGain (should be cached by API)
|
||||
const trackData = await this.api.getTrack(track.id, this.quality);
|
||||
|
|
@ -282,13 +304,27 @@ export class Player {
|
|||
} else {
|
||||
streamUrl = this.api.extractStreamUrlFromManifest(trackData.info.manifest);
|
||||
}
|
||||
}
|
||||
|
||||
this.audio.src = streamUrl;
|
||||
if (startTime > 0) {
|
||||
this.audio.currentTime = startTime;
|
||||
// Handle playback
|
||||
if (streamUrl && streamUrl.startsWith('blob:') && !track.isLocal) {
|
||||
// It's likely a DASH manifest blob URL
|
||||
this.dashPlayer.initialize(this.audio, streamUrl, true);
|
||||
this.dashInitialized = true;
|
||||
if (startTime > 0) {
|
||||
this.dashPlayer.seek(startTime);
|
||||
}
|
||||
} else {
|
||||
if (this.dashInitialized) {
|
||||
this.dashPlayer.reset();
|
||||
this.dashInitialized = false;
|
||||
}
|
||||
this.audio.src = streamUrl;
|
||||
if (startTime > 0) {
|
||||
this.audio.currentTime = startTime;
|
||||
}
|
||||
await this.audio.play();
|
||||
}
|
||||
}
|
||||
await this.audio.play();
|
||||
|
||||
// Update Media Session AFTER play starts to ensure metadata is captured
|
||||
this.updateMediaSession(track);
|
||||
|
|
@ -674,4 +710,4 @@ export class Player {
|
|||
updateBtn(timerBtn);
|
||||
updateBtn(timerBtnDesktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
330
package-lock.json
generated
330
package-lock.json
generated
|
|
@ -9,6 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"dashjs": "^5.1.1",
|
||||
"pocketbase": "^0.26.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -73,6 +74,7 @@
|
|||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
|
|
@ -1602,6 +1604,7 @@
|
|||
"integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@keyv/serialize": "^1.1.1"
|
||||
}
|
||||
|
|
@ -1643,6 +1646,7 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
|
|
@ -1686,6 +1690,7 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
|
|
@ -3021,6 +3026,130 @@
|
|||
"string.prototype.matchall": "^4.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-608": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-608/-/cml-608-1.0.1.tgz",
|
||||
"integrity": "sha512-Y/Ier9VPUSOBnf0bJqdDyTlPrt4dDB+jk5mYHa1bnD2kcRl8qn7KkW3PRuj4w1aVN+BS2eHmsLxodt7P2hylUg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-cmcd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-cmcd/-/cml-cmcd-1.0.1.tgz",
|
||||
"integrity": "sha512-eox305g+QUJgXqOLVrbgxeQHCgl90ewwQ9O2bIoo7m+hanR8Xswu5CknFnT5qqIbLOHfw80ug+raycoAFHTQ+w==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-cta": "1.0.1",
|
||||
"@svta/cml-structured-field-values": "1.0.1",
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-cmsd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-cmsd/-/cml-cmsd-1.0.1.tgz",
|
||||
"integrity": "sha512-+nIB8PuSfb/qw+xGaArPhNqPm84tBJUbe3H1DnPL5QUsjSUI7mUIUQwAtRV1ZdEu0+80g9i0op79woB0OIwr/g==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-cta": "1.0.1",
|
||||
"@svta/cml-structured-field-values": "1.0.1",
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-cta": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-cta/-/cml-cta-1.0.1.tgz",
|
||||
"integrity": "sha512-jcXqNIPv26bmFxIOFh8/c3+6WLH4qBjKpq9qTQcggDPoHuV1YBydMsJLOnYPDeK8rNMKcAkFLbnDRvyJthu5yw==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-structured-field-values": "1.0.1",
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-dash": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-dash/-/cml-dash-1.0.1.tgz",
|
||||
"integrity": "sha512-lYnD1I7FUbbQND+xICI+kcRaRXuT+whKk27R8m8me5VMVu2sMsAMc7Yui6l9sxw2cBKt8pSETPYRm/1+n4LZkw==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-id3": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-id3/-/cml-id3-1.0.1.tgz",
|
||||
"integrity": "sha512-90fGlL1qRI88CcaB89k6NG6cC3kky4Eu2jwqU4HefqK+S5k2OASUxf8JXkGz+DsdaiY7sh51vGPYdolfBZS7ug==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-request": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-request/-/cml-request-1.0.1.tgz",
|
||||
"integrity": "sha512-enL19BuXUjFkDDDF9jdNwUclMNPRsagnjGAetVC7xcmpDMpEx+ZLgsDip6BFNg5p6izSEk/OyujTWW1r8bDNiA==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-utils": "1.0.1",
|
||||
"@svta/cml-xml": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-structured-field-values": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-structured-field-values/-/cml-structured-field-values-1.0.1.tgz",
|
||||
"integrity": "sha512-Kibciki59Pon3Pn/sl5uyrbJcSpZQDKqdCfDrokBvOdLoqqcd0oFrkEPsZBiuuIODX1CB80612xe8hopeFDyBA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-utils": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-utils/-/cml-utils-1.0.1.tgz",
|
||||
"integrity": "sha512-kso3curTJfp00I1mKFoBliBApjn4aPE+wF8cPucf7TrSDVWZDeLLuF14ASmUE9m7rnrqTTK4878VvmXaXcCCfQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/@svta/cml-xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@svta/cml-xml/-/cml-xml-1.0.1.tgz",
|
||||
"integrity": "sha512-11LkJa5kDEcsRMWkVI1ABH3KLCxGoiSVe4kQ293ItVj8ncTTQ7htmCGiJDjS+Cmy35UgF3e/vc0ysJIiWRTx2g==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@svta/cml-utils": "1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
|
|
@ -3062,6 +3191,7 @@
|
|||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
|
|
@ -3085,6 +3215,7 @@
|
|||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
|
|
@ -3290,6 +3421,45 @@
|
|||
"baseline-browser-mapping": "dist/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/bcp-47": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz",
|
||||
"integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-alphabetical": "^2.0.0",
|
||||
"is-alphanumerical": "^2.0.0",
|
||||
"is-decimal": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/bcp-47-match": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz",
|
||||
"integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/bcp-47-normalize": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz",
|
||||
"integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bcp-47": "^2.0.0",
|
||||
"bcp-47-match": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
|
|
@ -3333,6 +3503,7 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.9.0",
|
||||
"caniuse-lite": "^1.0.30001759",
|
||||
|
|
@ -3492,6 +3663,12 @@
|
|||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/codem-isoboxer": {
|
||||
"version": "0.3.10",
|
||||
"resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.10.tgz",
|
||||
"integrity": "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
|
|
@ -3653,6 +3830,30 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/dashjs": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dashjs/-/dashjs-5.1.1.tgz",
|
||||
"integrity": "sha512-BzNXlUgzEjhuZ5M5hlSp1qIyQHZ7NpXAR0loP9DAAFVZj/ntL1DHeZ7qp/L3bvI4rq50X5indkAZQ3zEHWJoCA==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@svta/cml-608": "1.0.1",
|
||||
"@svta/cml-cmcd": "1.0.1",
|
||||
"@svta/cml-cmsd": "1.0.1",
|
||||
"@svta/cml-dash": "1.0.1",
|
||||
"@svta/cml-id3": "1.0.1",
|
||||
"@svta/cml-request": "1.0.1",
|
||||
"@svta/cml-xml": "1.0.1",
|
||||
"bcp-47-match": "^2.0.3",
|
||||
"bcp-47-normalize": "^2.3.0",
|
||||
"codem-isoboxer": "0.3.10",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"html-entities": "^2.5.2",
|
||||
"imsc": "^1.1.5",
|
||||
"localforage": "^1.10.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"ua-parser-js": "^1.0.37"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
||||
|
|
@ -4087,6 +4288,7 @@
|
|||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
|
|
@ -4310,7 +4512,6 @@
|
|||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
|
|
@ -4965,6 +5166,22 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html-entities": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
|
||||
"integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/mdevils"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://patreon.com/mdevils"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/html-tags": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
|
||||
|
|
@ -5111,6 +5328,12 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||
|
|
@ -5128,6 +5351,15 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/imsc": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.5.tgz",
|
||||
"integrity": "sha512-V8je+CGkcvGhgl2C1GlhqFFiUOIEdwXbXLiu1Fcubvvbo+g9inauqT3l0pNYXGoLPBj3jxtZz9t+wCopMkwadQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"sax": "1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/imurmurhash": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
|
|
@ -5160,6 +5392,30 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-alphabetical": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
|
||||
"integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-alphanumerical": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
|
||||
"integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-alphabetical": "^2.0.0",
|
||||
"is-decimal": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||
|
|
@ -5302,6 +5558,16 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-decimal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
|
||||
"integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/wooorm"
|
||||
}
|
||||
},
|
||||
"node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
|
|
@ -5822,6 +6088,15 @@
|
|||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
|
|
@ -5829,6 +6104,15 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/localforage": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"lie": "3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
|
|
@ -6235,6 +6519,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/path-browserify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
|
||||
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
|
|
@ -6355,6 +6645,7 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
|
|
@ -6438,6 +6729,7 @@
|
|||
"integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
|
|
@ -6859,6 +7151,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
||||
"integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
|
|
@ -7381,6 +7679,7 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@csstools/css-parser-algorithms": "^3.0.5",
|
||||
"@csstools/css-syntax-patches-for-csstree": "^1.0.19",
|
||||
|
|
@ -7795,6 +8094,7 @@
|
|||
"integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.15.0",
|
||||
|
|
@ -7942,6 +8242,32 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/ua-parser-js": {
|
||||
"version": "1.0.41",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz",
|
||||
"integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ua-parser-js"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/faisalman"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/faisalman"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"ua-parser-js": "script/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/unbox-primitive": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
|
||||
|
|
@ -8093,6 +8419,7 @@
|
|||
"integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.27.0",
|
||||
"fdir": "^6.5.0",
|
||||
|
|
@ -8480,6 +8807,7 @@
|
|||
"integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
"source-map": "^0.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"pocketbase": "^0.26.5"
|
||||
"pocketbase": "^0.26.5",
|
||||
"dashjs": "^5.1.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue