diff --git a/.gitignore b/.gitignore
index ea49801..a31c2f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
docs/javascript/
docs/react/
node_modules/
+
+# Incremental compilation that speeds up monorepo builds
+*.tsbuildinfo
\ No newline at end of file
diff --git a/package.json b/package.json
index 047bcd2..b6933ca 100644
--- a/package.json
+++ b/package.json
@@ -22,4 +22,4 @@
"vite": "^7.2.0",
"ws": "^8.18.3"
}
-}
\ No newline at end of file
+}
diff --git a/packages/javascript/.gitignore b/packages/javascript/.gitignore
index 94b95d1..8e7e28a 100644
--- a/packages/javascript/.gitignore
+++ b/packages/javascript/.gitignore
@@ -2,3 +2,4 @@ node_modules
dist
yarn-error.log
docs
+cypress/screenshots
\ No newline at end of file
diff --git a/packages/javascript/cypress.config.ts b/packages/javascript/cypress.config.ts
new file mode 100644
index 0000000..c8e8d88
--- /dev/null
+++ b/packages/javascript/cypress.config.ts
@@ -0,0 +1,26 @@
+import { defineConfig } from 'cypress';
+
+export default defineConfig({
+ defaultBrowser: 'electron',
+ component: {
+ devServer: {
+ framework: 'react',
+ bundler: 'vite',
+ },
+ },
+
+ viewportHeight: 720,
+ viewportWidth: 1280,
+
+ e2e: {
+ setupNodeEvents(on) {
+ // This is required to log progress to the terminal whilst generating frames
+ on('task', {
+ log(message) {
+ console.log(message);
+ return null;
+ },
+ });
+ },
+ },
+});
diff --git a/packages/javascript/cypress/component/AudioStability.cy.ts b/packages/javascript/cypress/component/AudioStability.cy.ts
new file mode 100644
index 0000000..da5acb4
--- /dev/null
+++ b/packages/javascript/cypress/component/AudioStability.cy.ts
@@ -0,0 +1,156 @@
+import { SurfaceManager } from '../../src/state-based/SurfaceManager';
+
+describe('Audio stability tests', () => {
+ it('can wait without playing', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/sinwave@440hz.wav',
+ type: 'audio',
+ audioOutput: '',
+ keyframes: [
+ [now, { set: { t: 0, rate: 0 } }], // paused at start
+ [now + 60_000, { set: { rate: 1 } }], // play in 1 minute
+ ],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('audio').should('have.prop', 'paused', true);
+ cy.get('audio').should('have.prop', 'currentTime', 0);
+ });
+
+ it('recovers from a pause', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/metronome@120bpm.wav',
+ type: 'audio',
+ audioOutput: '',
+ keyframes: [[now, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.log('Interfere with audio element');
+ cy.get('audio').should('have.prop', 'paused', false);
+ cy.get('audio').invoke('trigger', 'pause');
+ cy.get('audio').should('have.prop', 'paused', true);
+
+ cy.wait(1000);
+
+ cy.log('audio should have recovered');
+ cy.get('audio').should('have.prop', 'paused', false);
+ cy.get('audio').invoke('prop', 'currentTime').should('be.greaterThan', 1.5);
+ });
+
+ it('recovers from a play', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/metronome@120bpm.wav',
+ type: 'audio',
+ audioOutput: '',
+ keyframes: [[now, { set: { t: 1_500, rate: 0 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ // Wait until audio ready
+ cy.get('audio')
+ .invoke('prop', 'currentTime')
+ .should(($time) => expect(parseFloat($time)).to.be.closeTo(1.5, 0.1));
+
+ cy.log('Interfere with audio element');
+ cy.get('audio').invoke('prop', 'paused').should('be.true');
+ cy.get('audio').invoke('prop', 'playbackRate', 1);
+ cy.get('audio').then(($audio) => $audio.get(0).play().catch(/* do nothing*/));
+ cy.get('audio').invoke('prop', 'paused').should('be.false');
+
+ cy.wait(1000);
+
+ cy.log('audio should have recovered');
+ cy.get('audio')
+ .invoke('prop', 'currentTime')
+ .should(($time) => expect(parseFloat($time)).to.be.closeTo(1.5, 0.1));
+ });
+
+ it('recovers from a seek', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/metronome@120bpm.wav',
+ type: 'audio',
+ audioOutput: '',
+ keyframes: [[now, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.log('Interfere with audio element');
+ cy.get('audio').invoke('prop', 'currentTime', 5);
+
+ cy.wait(500);
+
+ cy.log('audio should have recovered');
+ cy.get('audio').invoke('prop', 'currentTime').should('be.lessThan', 2);
+ });
+
+ it('recovers from volume change', () => {
+ const INITIAL_VOLUME = 0;
+ const CHANGED_VOLUME = 1;
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ type: 'audio',
+ file: 'cypress/fixtures/sinwave@440hz.wav',
+ audioOutput: '',
+ keyframes: [[now, { set: { t: 0, rate: 1, volume: INITIAL_VOLUME } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('audio').invoke('prop', 'volume', CHANGED_VOLUME);
+ cy.get('audio').should('have.prop', 'volume', CHANGED_VOLUME);
+
+ cy.wait(1000);
+
+ cy.get('audio').should('have.prop', 'volume', INITIAL_VOLUME);
+ });
+
+ it('recovers from audio element deletion', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ type: 'audio',
+ file: 'cypress/fixtures/sinwave@440hz.wav',
+ audioOutput: '',
+ keyframes: [[now, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('audio').should('exist');
+ cy.get('audio').invoke('remove');
+ cy.get('audio').should('not.exist');
+
+ cy.wait(1000);
+
+ cy.get('audio').should('exist');
+ });
+
+ it('smoothly returns to correct time using playbackRate', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ type: 'audio',
+ file: 'cypress/fixtures/metronome@120bpm.wav',
+ audioOutput: '',
+ keyframes: [[now - 500, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('audio').invoke('prop', 'currentTime').should('be.lessThan', 2);
+ });
+});
diff --git a/packages/javascript/cypress/component/ImageStability.cy.ts b/packages/javascript/cypress/component/ImageStability.cy.ts
new file mode 100644
index 0000000..9a7b721
--- /dev/null
+++ b/packages/javascript/cypress/component/ImageStability.cy.ts
@@ -0,0 +1,78 @@
+import { SurfaceManager } from '../../src/state-based/SurfaceManager';
+
+describe('Image stability tests', () => {
+ it('can show an image', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/indianred@2560x1440.png',
+ type: 'image',
+ fit: 'cover',
+ keyframes: [[now, { set: { opacity: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+ cy.get('img').should('exist');
+ });
+
+ it("doesn't show a queued image", () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/indianred@2560x1440.png',
+ type: 'image',
+ fit: 'cover',
+ keyframes: [
+ [now + 60_000, { set: { opacity: 1 } }], // show image in 1 minute
+ ],
+ },
+ });
+ cy.mount(manager);
+ cy.get('img').should('not.exist');
+ });
+
+ it('recovers from img element src change', () => {
+ const ORIGINAL_SRC = 'cypress/fixtures/indianred@2560x1440.png';
+ const CHANGED_SRC = '404.png';
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: ORIGINAL_SRC,
+ type: 'image',
+ fit: 'cover',
+ keyframes: [[now, { set: { opacity: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('img').should('exist');
+ cy.get('img').invoke('prop', 'src', CHANGED_SRC);
+
+ cy.wait(1_000);
+
+ cy.get('img')
+ .invoke('prop', 'src')
+ .should(($src) => expect($src).to.contain(ORIGINAL_SRC));
+ });
+
+ it('recovers from img element deletion', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/indianred@2560x1440.png',
+ type: 'image',
+ fit: 'cover',
+ keyframes: [[now, { set: { opacity: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('img').should('exist');
+ cy.get('img').invoke('remove');
+ cy.get('img').should('not.exist');
+
+ cy.wait(1_000);
+
+ cy.get('img').should('exist');
+ });
+});
diff --git a/packages/javascript/cypress/component/UpdatingSurfaceState.cy.ts b/packages/javascript/cypress/component/UpdatingSurfaceState.cy.ts
new file mode 100644
index 0000000..a796e6d
--- /dev/null
+++ b/packages/javascript/cypress/component/UpdatingSurfaceState.cy.ts
@@ -0,0 +1,61 @@
+import { DATA_CLIP_ID, SurfaceManager } from '../../src/state-based/SurfaceManager';
+
+describe('Updating surface state', () => {
+ it('adds and removes a video clip', () => {
+ const manager = new SurfaceManager({});
+ cy.mount(manager);
+
+ cy.get('video')
+ .should('not.exist')
+ .then(() => {
+ const now = Date.now();
+ manager.setState({
+ 'clip-id': {
+ file: 'cypress/fixtures/2x2s@2560x1440.mp4',
+ type: 'video',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [
+ [now + 1_000, { set: { t: 0, rate: 1 } }], // play in 1s
+ ],
+ },
+ });
+ })
+ .then(() => {
+ // This implicitly waits
+ cy.get('video').should('exist');
+ })
+ .then(() => {
+ manager.setState({});
+ })
+ .then(() => {
+ cy.get('video').should('not.exist');
+ });
+ });
+
+ it('adds multiple media', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({});
+ cy.mount(manager);
+ expect(manager.element.children.length).to.eq(0);
+
+ manager.setState({
+ 'image-background': {
+ type: 'image',
+ file: 'cypress/fixtures/indianred@2560x1440.png',
+ fit: 'cover',
+ keyframes: [[now, {}]],
+ },
+ 'video-foreground': {
+ type: 'video',
+ fit: 'contain',
+ audioOutput: '',
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ keyframes: [[now, {}]],
+ },
+ });
+
+ cy.get(`[${DATA_CLIP_ID}=image-background]`).should('exist');
+ cy.get(`[${DATA_CLIP_ID}=video-foreground]`).should('exist');
+ });
+});
diff --git a/packages/javascript/cypress/component/VideoStability.cy.ts b/packages/javascript/cypress/component/VideoStability.cy.ts
new file mode 100644
index 0000000..2c303c3
--- /dev/null
+++ b/packages/javascript/cypress/component/VideoStability.cy.ts
@@ -0,0 +1,163 @@
+import { SurfaceManager } from '../../src/state-based/SurfaceManager';
+
+describe('Video stability tests', () => {
+ it('can wait without playing', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ type: 'video',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [
+ [now, { set: { t: 0, rate: 0 } }], // paused at start
+ [now + 60_000, { set: { rate: 1 } }], // play in 1 minute
+ ],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('video').should('have.prop', 'paused', true);
+ cy.get('video').should('have.prop', 'currentTime', 0);
+ });
+
+ it('recovers from a pause', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ type: 'video',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [[now, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.log('Interfere with video element');
+ cy.get('video').should('have.prop', 'paused', false);
+ cy.get('video').invoke('trigger', 'pause');
+ cy.get('video').should('have.prop', 'paused', true);
+
+ cy.wait(1000);
+
+ cy.log('Video should have recovered');
+ cy.get('video').should('have.prop', 'paused', false);
+ cy.get('video').invoke('prop', 'currentTime').should('be.greaterThan', 1.5);
+ });
+
+ it('recovers from a play', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ type: 'video',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [[now, { set: { t: 1_500, rate: 0 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ // Wait until video ready
+ cy.get('video')
+ .invoke('prop', 'currentTime')
+ .should(($time) => expect(parseFloat($time)).to.be.closeTo(1.5, 0.1));
+
+ cy.log('Interfere with video element');
+ cy.get('video').invoke('prop', 'paused').should('be.true');
+ cy.get('video').invoke('prop', 'playbackRate', 1);
+ cy.get('video').then(($video) => $video.get(0).play().catch(/* do nothing*/));
+ cy.get('video').invoke('prop', 'paused').should('be.false');
+
+ cy.wait(1000);
+
+ cy.log('Video should have recovered');
+ cy.get('video')
+ .invoke('prop', 'currentTime')
+ .should(($time) => expect(parseFloat($time)).to.be.closeTo(1.5, 0.1));
+ });
+
+ it('recovers from a seek', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ type: 'video',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [[now, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.log('Interfere with video element');
+ cy.get('video').invoke('prop', 'currentTime', 5);
+
+ cy.wait(500);
+
+ cy.log('Video should have recovered');
+ cy.get('video').invoke('prop', 'currentTime').should('be.lessThan', 2);
+ });
+
+ it('recovers from volume change', () => {
+ const INITIAL_VOLUME = 0;
+ const CHANGED_VOLUME = 1;
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ type: 'video',
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [[now, { set: { t: 0, rate: 1, volume: INITIAL_VOLUME } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('video').invoke('prop', 'volume', CHANGED_VOLUME);
+ cy.get('video').should('have.prop', 'volume', CHANGED_VOLUME);
+
+ cy.wait(1000);
+
+ cy.get('video').should('have.prop', 'volume', INITIAL_VOLUME);
+ });
+
+ it('recovers from video element deletion', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ type: 'video',
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [[now, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('video').should('exist');
+ cy.get('video').invoke('remove');
+ cy.get('video').should('not.exist');
+
+ cy.wait(1000);
+
+ cy.get('video').should('exist');
+ });
+
+ it('smoothly returns to correct time using playbackRate', () => {
+ const now = Date.now();
+ const manager = new SurfaceManager({
+ 'clip-id': {
+ type: 'video',
+ file: 'cypress/fixtures/yuv444p~5x2s@2560x1440.mp4',
+ audioOutput: '',
+ fit: 'cover',
+ keyframes: [[now - 500, { set: { t: 0, rate: 1 } }]],
+ },
+ });
+ cy.mount(manager);
+
+ cy.get('video').invoke('prop', 'currentTime').should('be.lessThan', 2);
+ });
+});
diff --git a/packages/javascript/cypress/e2e/generate-test-video-frames.cy.ts b/packages/javascript/cypress/e2e/generate-test-video-frames.cy.ts
new file mode 100644
index 0000000..e462240
--- /dev/null
+++ b/packages/javascript/cypress/e2e/generate-test-video-frames.cy.ts
@@ -0,0 +1,24 @@
+const LOOP_DURATION = 2_000;
+const FPS = 60;
+const TOTAL_LOOPS = 2;
+const TOTAL_FRAMES = Math.floor(LOOP_DURATION * (FPS / 1000) * TOTAL_LOOPS);
+
+describe('template spec', () => {
+ it('testing', { baseUrl: null }, () => {
+ const frameDuration = 1000 / FPS;
+ let frame = 0;
+ let ms = 0;
+
+ while (frame < TOTAL_FRAMES) {
+ // Debug log for long running tasks
+ cy.task('log', `[frame: ${frame + 1}/${TOTAL_FRAMES}] [ms: ${ms.toFixed(2)}/${TOTAL_LOOPS * LOOP_DURATION}]`);
+ // Go to new frame of the video
+ cy.visit(`cypress/e2e/test-video.html?loopDurationMs=${LOOP_DURATION}¤tMs=${ms}`);
+ // Capture screenshot
+ cy.screenshot(`${frame}`, { capture: 'viewport', overwrite: true });
+ // Set up for next iteration
+ frame++;
+ ms = frame * frameDuration;
+ }
+ });
+});
diff --git a/packages/javascript/cypress/e2e/test-video.html b/packages/javascript/cypress/e2e/test-video.html
new file mode 100644
index 0000000..b7c793f
--- /dev/null
+++ b/packages/javascript/cypress/e2e/test-video.html
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/javascript/cypress/fixtures/indianred@2560x1440.png b/packages/javascript/cypress/fixtures/indianred@2560x1440.png
new file mode 100644
index 0000000..e2f69ac
Binary files /dev/null and b/packages/javascript/cypress/fixtures/indianred@2560x1440.png differ
diff --git a/packages/javascript/cypress/fixtures/metronome@120bpm.wav b/packages/javascript/cypress/fixtures/metronome@120bpm.wav
new file mode 100644
index 0000000..21973e4
Binary files /dev/null and b/packages/javascript/cypress/fixtures/metronome@120bpm.wav differ
diff --git a/packages/javascript/cypress/fixtures/sinwave@440hz.wav b/packages/javascript/cypress/fixtures/sinwave@440hz.wav
new file mode 100644
index 0000000..d5882d6
Binary files /dev/null and b/packages/javascript/cypress/fixtures/sinwave@440hz.wav differ
diff --git a/packages/javascript/cypress/fixtures/yuv420p~2x2s@2560x1440.mp4 b/packages/javascript/cypress/fixtures/yuv420p~2x2s@2560x1440.mp4
new file mode 100644
index 0000000..291227b
Binary files /dev/null and b/packages/javascript/cypress/fixtures/yuv420p~2x2s@2560x1440.mp4 differ
diff --git a/packages/javascript/cypress/fixtures/yuv420p~5x2s@2560x1440.mp4 b/packages/javascript/cypress/fixtures/yuv420p~5x2s@2560x1440.mp4
new file mode 100644
index 0000000..e044643
Binary files /dev/null and b/packages/javascript/cypress/fixtures/yuv420p~5x2s@2560x1440.mp4 differ
diff --git a/packages/javascript/cypress/fixtures/yuv444p~2x2s@2560x1440.mp4 b/packages/javascript/cypress/fixtures/yuv444p~2x2s@2560x1440.mp4
new file mode 100644
index 0000000..0ea41b4
Binary files /dev/null and b/packages/javascript/cypress/fixtures/yuv444p~2x2s@2560x1440.mp4 differ
diff --git a/packages/javascript/cypress/fixtures/yuv444p~5x2s@2560x1440.mp4 b/packages/javascript/cypress/fixtures/yuv444p~5x2s@2560x1440.mp4
new file mode 100644
index 0000000..8d0e7a6
Binary files /dev/null and b/packages/javascript/cypress/fixtures/yuv444p~5x2s@2560x1440.mp4 differ
diff --git a/packages/javascript/cypress/mount.ts b/packages/javascript/cypress/mount.ts
new file mode 100644
index 0000000..ad6400b
--- /dev/null
+++ b/packages/javascript/cypress/mount.ts
@@ -0,0 +1,25 @@
+import { getContainerEl, setupHooks } from '@cypress/mount-utils';
+import { SurfaceManager } from '../src/state-based/SurfaceManager';
+
+export function mount(surfaceManager: SurfaceManager): Cypress.Chainable {
+ const container = getContainerEl();
+
+ // 100% styling
+ document.body.style.margin = '0';
+ container.style.width = '100vw';
+ container.style.height = '100vh';
+
+ // clean up each time we mount a new component
+ container.innerHTML = '';
+ const prevManager = (window as any).surfaceManager as SurfaceManager;
+ prevManager?.setState({});
+
+ // mount component
+ (window as any).surfaceManager = surfaceManager;
+ container.append(surfaceManager.element);
+
+ // initialize internal pre/post test hooks
+ setupHooks();
+
+ return cy.wrap(surfaceManager.element, { log: false });
+}
diff --git a/packages/javascript/cypress/support/commands.ts b/packages/javascript/cypress/support/commands.ts
new file mode 100644
index 0000000..95857ae
--- /dev/null
+++ b/packages/javascript/cypress/support/commands.ts
@@ -0,0 +1,37 @@
+///
+// ***********************************************
+// This example commands.ts shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
+//
+// declare global {
+// namespace Cypress {
+// interface Chainable {
+// login(email: string, password: string): Chainable
+// drag(subject: string, options?: Partial): Chainable
+// dismiss(subject: string, options?: Partial): Chainable
+// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable
+// }
+// }
+// }
diff --git a/packages/javascript/cypress/support/component-index.html b/packages/javascript/cypress/support/component-index.html
new file mode 100644
index 0000000..ac6e79f
--- /dev/null
+++ b/packages/javascript/cypress/support/component-index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Components App
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/javascript/cypress/support/component.ts b/packages/javascript/cypress/support/component.ts
new file mode 100644
index 0000000..4ec8287
--- /dev/null
+++ b/packages/javascript/cypress/support/component.ts
@@ -0,0 +1,36 @@
+/* eslint-disable @typescript-eslint/no-namespace */
+// ***********************************************************
+// This example support/component.ts is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import { mount } from '../mount';
+import './commands';
+
+// Augment the Cypress namespace to include type definitions for
+// your custom command.
+// Alternatively, can be defined in cypress/support/component.d.ts
+// with a at the top of your spec.
+declare global {
+ namespace Cypress {
+ interface Chainable {
+ mount: typeof mount;
+ }
+ }
+}
+
+Cypress.Commands.add('mount', mount);
+
+// Example use:
+// cy.mount()
diff --git a/packages/javascript/cypress/support/e2e.ts b/packages/javascript/cypress/support/e2e.ts
new file mode 100644
index 0000000..e66558e
--- /dev/null
+++ b/packages/javascript/cypress/support/e2e.ts
@@ -0,0 +1,17 @@
+// ***********************************************************
+// This example support/e2e.ts is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands';
diff --git a/packages/javascript/cypress/tsconfig.json b/packages/javascript/cypress/tsconfig.json
new file mode 100644
index 0000000..479d839
--- /dev/null
+++ b/packages/javascript/cypress/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["es5", "dom"],
+ "sourceMap": true,
+ "types": ["cypress", "node"],
+ "jsx": "react"
+ },
+ "include": ["**/*.ts"]
+}
\ No newline at end of file
diff --git a/packages/javascript/package.json b/packages/javascript/package.json
index 152c641..b74eef1 100644
--- a/packages/javascript/package.json
+++ b/packages/javascript/package.json
@@ -22,7 +22,7 @@
"default": "./dist/index.js"
},
"scripts": {
- "test": "yarn types && yarn lint && vitest",
+ "test": "yarn types && yarn lint && vitest && yarn cy:run",
"types": "tsc --noEmit",
"lint": "eslint .",
"build": "yarn build:ts && yarn build:browser",
@@ -31,7 +31,10 @@
"watch-build": "tsc -w",
"build-docs": "typedoc --out ../../docs/javascript --name @clockworkdog/cogs-client src/index.ts",
"release": "yarn npm publish --access public",
- "prerelease": "yarn npm publish --access public --tag=next"
+ "prerelease": "yarn npm publish --access public --tag=next",
+ "cy:open": "cypress open",
+ "cy:run": "cypress run --component",
+ "cy:generate": "cypress run --e2e"
},
"dependencies": {
"@clockworkdog/timesync": "workspace:^",
@@ -40,15 +43,19 @@
"zod": "^4.1.13"
},
"devDependencies": {
+ "@cypress/mount-utils": "^4.1.2",
"@eslint/js": "^9.17.0",
"@types/howler": "2.2.12",
"@types/jsdom": "^27",
"@types/node": "^22.10.2",
+ "cypress": "^14.5.4",
"eslint": "^9.17.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"jsdom": "^27.1.0",
"prettier": "^3.4.2",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
"typedoc": "^0.27.5",
"typescript": "~5.7.2",
"typescript-eslint": "^8.18.1",
diff --git a/packages/javascript/scripts/generate-video.ts b/packages/javascript/scripts/generate-video.ts
new file mode 100644
index 0000000..f6aca1f
--- /dev/null
+++ b/packages/javascript/scripts/generate-video.ts
@@ -0,0 +1,49 @@
+import { spawn } from 'node:child_process';
+const ffmpeg = 'ffmpeg';
+
+/**
+ * - First make sure cypress/screenshots is empty
+ * This is the directory we'll use to save all video frames
+ * - Then run `yarn cy:generate`
+ * This will run the generate procedure in the e2e test
+ * It will save screenshots to cypres/screenshots
+ * - Finally run this file to create a test video
+ */
+
+const child = spawn(ffmpeg, [
+ // Set the input framerate
+ '-framerate',
+ '60',
+ // Specify the input files
+ '-i',
+ 'cypress/screenshots/generate-test-video-frames.cy.ts/%d.png',
+ // Set the output framerate
+ '-r',
+ '60',
+ // specify the codec
+ '-c:v',
+ 'libx264',
+ // pixel format
+ '-pix_fmt',
+ 'yuv420p',
+ // automatically overwrite
+ '-y',
+ // destination
+ 'out.mp4',
+]);
+
+child.stdout.on('data', (data) => console.log(data.toString()));
+child.stderr.on('data', (data) => console.error(data.toString()));
+
+child.on('error', () => {
+ console.error('Failed to generate video');
+ process.exit(1);
+});
+
+child.on('close', (code) => {
+ if (code === 0) {
+ console.log('Created video');
+ } else {
+ console.error('Failed to create video');
+ }
+});
diff --git a/packages/javascript/src/index.ts b/packages/javascript/src/index.ts
index 30e218b..0936e65 100644
--- a/packages/javascript/src/index.ts
+++ b/packages/javascript/src/index.ts
@@ -7,6 +7,7 @@ export type { default as MediaObjectFit } from './types/MediaObjectFit';
export * as MediaSchema from './types/MediaSchema';
export { default as CogsAudioPlayer } from './AudioPlayer';
export { default as CogsVideoPlayer } from './VideoPlayer';
+export { SurfaceManager } from './state-based/SurfaceManager';
export * from './types/AudioState';
export { assetUrl, preloadUrl } from './utils/urls';
export { getStateAtTime } from './utils/getStateAtTime';
diff --git a/packages/javascript/src/state-based/AudioManager.ts b/packages/javascript/src/state-based/AudioManager.ts
new file mode 100644
index 0000000..999a26e
--- /dev/null
+++ b/packages/javascript/src/state-based/AudioManager.ts
@@ -0,0 +1,125 @@
+import { AudioState, defaultAudioOptions } from '../types/MediaSchema';
+import { getStateAtTime } from '../utils/getStateAtTime';
+import { ClipManager } from './ClipManager';
+
+const DEFAULT_AUDIO_POLLING = 1_000;
+const TARGET_SYNC_THRESHOLD_MS = 10; // If we're closer than this we're good enough
+const MAX_SYNC_THRESHOLD_MS = 1_000; // If we're further away than this, we'll seek instead
+const SEEK_LOOKAHEAD_MS = 200; // We won't seek ahead instantly, so lets seek ahead
+const MAX_PLAYBACK_RATE_ADJUSTMENT = 0.2;
+// We smoothly ramp playbackRate up and down
+const PLAYBACK_ADJUSTMENT_SMOOTHING = 0.5;
+function playbackSmoothing(deltaTime: number) {
+ return Math.sign(deltaTime) * Math.pow(Math.abs(deltaTime) / MAX_SYNC_THRESHOLD_MS, PLAYBACK_ADJUSTMENT_SMOOTHING) * MAX_PLAYBACK_RATE_ADJUSTMENT;
+}
+
+export class AudioManager extends ClipManager {
+ private audioElement?: HTMLAudioElement;
+ private isSeeking = false;
+
+ constructor(surfaceElement: HTMLElement, clipElement: HTMLElement, state: AudioState) {
+ super(surfaceElement, clipElement, state);
+ this.clipElement = clipElement;
+ }
+
+ private updateAudioElement() {
+ this.destroy();
+ this.audioElement = document.createElement('audio');
+ this.clipElement.replaceChildren(this.audioElement);
+ }
+
+ /**
+ * Helper function to seek to a specified time.
+ * Works with the update loop to poll until seeked event has fired.
+ */
+ private seekTo(time: number) {
+ if (!this.audioElement) return;
+ this.audioElement.addEventListener(
+ 'seeked',
+ () => {
+ this.isSeeking = false;
+ },
+ { once: true, passive: true },
+ );
+ this.audioElement.currentTime = time / 1_000;
+ }
+
+ protected update(): void {
+ // Update loop used to poll until seek finished
+ if (this.isSeeking) return;
+ this.delay = DEFAULT_AUDIO_POLLING;
+
+ // Does the element need adding/removing?
+ const currentState = getStateAtTime(this._state, Date.now());
+ if (currentState) {
+ if (!this.audioElement || !this.isConnected(this.audioElement)) {
+ this.updateAudioElement();
+ }
+ } else {
+ this.destroy();
+ }
+
+ if (!currentState || !this.audioElement) return;
+ const { t, rate, volume } = { ...defaultAudioOptions, ...currentState };
+
+ // this.audioElement.src will be a fully qualified URL
+ if (!this.audioElement.src.endsWith(this._state.file)) {
+ this.audioElement.src = this._state.file;
+ }
+ if (this.audioElement.volume !== volume) {
+ this.audioElement.volume = volume;
+ }
+
+ // Should the element be playing?
+ if (this.audioElement.paused && rate > 0) {
+ this.audioElement.play().catch(() => {
+ // Do nothing - this will be retried in the next loop
+ });
+ }
+
+ const currentTime = this.audioElement.currentTime * 1000;
+ const deltaTime = currentTime - t;
+ const deltaTimeAbs = Math.abs(deltaTime);
+ this.delay = 100;
+ switch (true) {
+ case deltaTimeAbs <= TARGET_SYNC_THRESHOLD_MS:
+ // We are on course:
+ // - The audio is within accepted latency of the server time
+ // - The playback rate is aligned with the server rate
+ if (this.audioElement.playbackRate !== rate) {
+ this.audioElement.playbackRate = rate;
+ }
+ break;
+ case rate > 0 && deltaTimeAbs > TARGET_SYNC_THRESHOLD_MS && deltaTimeAbs <= MAX_SYNC_THRESHOLD_MS: {
+ // We are close, we can smoothly adjust with playbackRate:
+ // - The audio must be playing
+ // - We must be close in time to the server time
+ const playbackRateAdjustment = playbackSmoothing(deltaTime);
+ const adjustedPlaybackRate = Math.max(0, rate - playbackRateAdjustment);
+ if (this.audioElement.playbackRate !== adjustedPlaybackRate) {
+ this.audioElement.playbackRate = adjustedPlaybackRate;
+ }
+ break;
+ }
+ default: {
+ // We cannot smoothly recover:
+ // - We seek just ahead of server time
+ if (this.audioElement.playbackRate !== rate) {
+ this.audioElement.playbackRate = rate;
+ }
+
+ // delay to poll until seeked
+ this.delay = 10;
+ this.seekTo(t + rate * (SEEK_LOOKAHEAD_MS / 1000));
+ break;
+ }
+ }
+ }
+
+ destroy(): void {
+ if (this.audioElement) {
+ this.audioElement.src = '';
+ this.audioElement.remove();
+ }
+ }
+}
diff --git a/packages/javascript/src/state-based/ClipManager.ts b/packages/javascript/src/state-based/ClipManager.ts
new file mode 100644
index 0000000..532e636
--- /dev/null
+++ b/packages/javascript/src/state-based/ClipManager.ts
@@ -0,0 +1,62 @@
+import { MediaClipState } from '../types/MediaSchema';
+const DEFAULT_DELAY = 1_000;
+
+/**
+ * Each instance of a ClipManager is responsible for displaying
+ * an image/audio/video clip in the correct state.
+ */
+export abstract class ClipManager {
+ constructor(
+ private surfaceElement: HTMLElement,
+ protected clipElement: HTMLElement,
+ state: T,
+ ) {
+ this._state = state;
+ // Allow the class to be constructed, then call the loop
+ setTimeout(this.loop);
+ }
+
+ /**
+ * This is the delay to be used in the update loop.
+ * It is intended to be dynamic for each loop.
+ */
+ protected delay = DEFAULT_DELAY;
+
+ protected abstract update(): void;
+ public abstract destroy(): void;
+
+ isConnected(element?: HTMLElement) {
+ if (!this.surfaceElement) {
+ return false;
+ }
+ if (!this.clipElement) {
+ return false;
+ }
+ if (!this.surfaceElement.contains(this.clipElement)) {
+ return false;
+ }
+
+ if (element) {
+ if (!this.clipElement.contains(element)) return false;
+ }
+
+ return true;
+ }
+
+ protected _state: T;
+ setState(newState: T) {
+ this._state = newState;
+ clearTimeout(this.timeout);
+ this.loop();
+ }
+
+ private timeout: ReturnType | undefined;
+ private loop = async () => {
+ if (this.isConnected()) {
+ this.update();
+ this.timeout = setTimeout(this.loop, this.delay);
+ } else {
+ this.destroy();
+ }
+ };
+}
diff --git a/packages/javascript/src/state-based/ImageManager.ts b/packages/javascript/src/state-based/ImageManager.ts
new file mode 100644
index 0000000..7f75ea5
--- /dev/null
+++ b/packages/javascript/src/state-based/ImageManager.ts
@@ -0,0 +1,52 @@
+import { ImageState } from '../types/MediaSchema';
+import { getStateAtTime } from '../utils/getStateAtTime';
+import { ClipManager } from './ClipManager';
+
+export class ImageManager extends ClipManager {
+ private imageElement?: HTMLImageElement;
+
+ constructor(surfaceElement: HTMLElement, clipElement: HTMLElement, state: ImageState) {
+ super(surfaceElement, clipElement, state);
+ this.clipElement = clipElement;
+ }
+
+ private updateImageElement() {
+ this.imageElement = document.createElement('img');
+ this.clipElement.replaceChildren(this.imageElement);
+ this.imageElement.style.position = 'absolute';
+ this.imageElement.style.height = '100%';
+ this.imageElement.style.widows = '100%';
+ }
+
+ protected update(): void {
+ const currentState = getStateAtTime(this._state, Date.now());
+
+ // Does the
element need adding/removing?
+ if (currentState) {
+ if (!this.imageElement || !this.isConnected(this.imageElement)) {
+ this.updateImageElement();
+ }
+ } else {
+ this.imageElement?.remove();
+ this.imageElement = undefined;
+ }
+ if (!this.imageElement || !currentState) return;
+
+ // this.imageElement.src will be a fully qualified URL
+ if (!this.imageElement.src.startsWith(this._state.file)) {
+ this.imageElement.src = this._state.file;
+ }
+ if (this.imageElement.style.objectFit !== this._state.fit) {
+ this.imageElement.style.objectFit = this._state.fit;
+ }
+
+ const { opacity } = currentState;
+ if (typeof opacity === 'string' && opacity !== this.imageElement.style.opacity) {
+ this.imageElement.style.opacity = opacity;
+ }
+ }
+
+ destroy(): void {
+ this.imageElement?.remove();
+ }
+}
diff --git a/packages/javascript/src/state-based/SurfaceManager.ts b/packages/javascript/src/state-based/SurfaceManager.ts
new file mode 100644
index 0000000..27f5f73
--- /dev/null
+++ b/packages/javascript/src/state-based/SurfaceManager.ts
@@ -0,0 +1,90 @@
+import { MediaClipState, MediaSurfaceState } from '../types/MediaSchema';
+import { ClipManager } from './ClipManager';
+import { ImageManager } from './ImageManager';
+import { VideoManager } from './VideoManager';
+import { AudioManager } from './AudioManager';
+
+export const DATA_CLIP_ID = 'data-clip-id';
+type TaggedElement = HTMLElement & { [DATA_CLIP_ID]?: string };
+
+/**
+ * The SurfaceManager will receive state updates and:
+ * - Ensure that each clip has a parent element
+ * - Instantiate a ClipManager attached to each respective element
+ */
+export class SurfaceManager {
+ private _state: MediaSurfaceState = {};
+ public setState(newState: MediaSurfaceState) {
+ this._state = newState;
+ this.update();
+ }
+ private _element: HTMLDivElement;
+ public get element() {
+ return this._element;
+ }
+
+ private resources: { [clipId: string]: { element: HTMLElement; manager?: ClipManager } } = {};
+
+ constructor(testState?: MediaSurfaceState) {
+ this._element = document.createElement('div');
+ this._element.style.width = '100%';
+ this._element.style.height = '100%';
+
+ this._state = testState || {};
+ this.update();
+ }
+
+ update() {
+ // Destroy stale managers
+ Object.entries(this.resources).forEach(([clipId, { element, manager }]) => {
+ if (!(clipId in this._state)) {
+ delete this.resources[clipId];
+ element.remove();
+ manager?.destroy();
+ }
+ });
+
+ // Create and attach new wrapper elements
+ const elements = Object.keys(this._state)
+ .toSorted()
+ .map((clipId) => {
+ const resource = this.resources[clipId];
+ if (resource) {
+ return resource.element;
+ } else {
+ const element = document.createElement('div') as TaggedElement;
+ element.setAttribute(DATA_CLIP_ID, clipId);
+ this.resources[clipId] = { element };
+ return element;
+ }
+ });
+ this._element.replaceChildren(...elements);
+
+ // Create new managers
+ Object.keys(this._state)
+ .toSorted()
+ .forEach((clipId) => {
+ const clip = this._state[clipId]!;
+ const resource = this.resources[clipId];
+ if (!resource) {
+ throw new Error('Failed to create resource');
+ }
+
+ if (!resource.manager) {
+ switch (clip.type) {
+ case 'image':
+ resource.manager = new ImageManager(this._element, resource.element, clip);
+ break;
+ case 'audio':
+ resource.manager = new AudioManager(this._element, resource.element, clip);
+ break;
+ case 'video':
+ resource.manager = new VideoManager(this._element, resource.element, clip);
+ break;
+ }
+ } else {
+ resource.manager.setState(clip);
+ }
+ });
+ }
+}
diff --git a/packages/javascript/src/state-based/VideoManager.ts b/packages/javascript/src/state-based/VideoManager.ts
new file mode 100644
index 0000000..5fbfdf5
--- /dev/null
+++ b/packages/javascript/src/state-based/VideoManager.ts
@@ -0,0 +1,132 @@
+import { defaultVideoOptions, VideoState } from '../types/MediaSchema';
+import { getStateAtTime } from '../utils/getStateAtTime';
+import { ClipManager } from './ClipManager';
+
+const DEFAULT_VIDEO_POLLING = 1_000;
+const TARGET_SYNC_THRESHOLD_MS = 10; // If we're closer than this we're good enough
+const MAX_SYNC_THRESHOLD_MS = 1_000; // If we're further away than this, we'll seek instead
+const SEEK_LOOKAHEAD_MS = 200; // We won't seek ahead instantly, so lets seek ahead
+const MAX_PLAYBACK_RATE_ADJUSTMENT = 0.5;
+// We smoothly ramp playbackRate up and down
+const PLAYBACK_ADJUSTMENT_SMOOTHING = 0.3;
+function playbackSmoothing(deltaTime: number) {
+ return Math.sign(deltaTime) * Math.pow(Math.abs(deltaTime) / MAX_SYNC_THRESHOLD_MS, PLAYBACK_ADJUSTMENT_SMOOTHING) * MAX_PLAYBACK_RATE_ADJUSTMENT;
+}
+
+export class VideoManager extends ClipManager {
+ private videoElement?: HTMLVideoElement;
+ private isSeeking = false;
+
+ constructor(surfaceElement: HTMLElement, clipElement: HTMLElement, state: VideoState) {
+ super(surfaceElement, clipElement, state);
+ this.clipElement = clipElement;
+ }
+
+ private updateVideoElement() {
+ this.destroy();
+ this.videoElement = document.createElement('video');
+ this.clipElement.replaceChildren(this.videoElement);
+ this.videoElement.style.position = 'absolute';
+ this.videoElement.style.width = '100%';
+ this.videoElement.style.height = '100%';
+ }
+
+ /**
+ * Helper function to seek to a specified time.
+ * Works with the update loop to poll until seeked event has fired.
+ */
+ private seekTo(time: number) {
+ if (!this.videoElement) return;
+ this.videoElement.addEventListener(
+ 'seeked',
+ () => {
+ this.isSeeking = false;
+ },
+ { once: true, passive: true },
+ );
+ this.videoElement.currentTime = time / 1_000;
+ }
+
+ protected update(): void {
+ // Update loop used to poll until seek finished
+ if (this.isSeeking) return;
+ this.delay = DEFAULT_VIDEO_POLLING;
+
+ // Does the element need adding/removing?
+ const currentState = getStateAtTime(this._state, Date.now());
+ if (currentState) {
+ if (!this.videoElement || !this.isConnected(this.videoElement)) {
+ this.updateVideoElement();
+ }
+ } else {
+ this.videoElement?.remove();
+ this.videoElement = undefined;
+ }
+
+ if (!currentState || !this.videoElement) return;
+ const { t, rate, volume } = { ...defaultVideoOptions, ...currentState };
+
+ // this.videoElement.src will be a fully qualified URL
+ if (!this.videoElement.src.endsWith(this._state.file)) {
+ this.videoElement.src = this._state.file;
+ }
+ if (this.videoElement.style.objectFit !== this._state.fit) {
+ this.videoElement.style.objectFit = this._state.fit;
+ }
+ if (this.videoElement.volume !== volume) {
+ this.videoElement.volume = volume;
+ }
+
+ // Should the element be playing?
+ if (this.videoElement.paused && rate > 0) {
+ this.videoElement.play().catch(() => {
+ // Do nothing - this will be retried in the next loop
+ });
+ }
+
+ const currentTime = this.videoElement.currentTime * 1000;
+ const deltaTime = currentTime - t;
+ const deltaTimeAbs = Math.abs(deltaTime);
+ this.delay = 100;
+ switch (true) {
+ case deltaTimeAbs <= TARGET_SYNC_THRESHOLD_MS:
+ // We are on course:
+ // - The video is within accepted latency of the server time
+ // - The playback rate is aligned with the server rate
+ if (this.videoElement.playbackRate !== rate) {
+ this.videoElement.playbackRate = rate;
+ }
+ break;
+ case rate > 0 && deltaTimeAbs > TARGET_SYNC_THRESHOLD_MS && deltaTimeAbs <= MAX_SYNC_THRESHOLD_MS: {
+ // We are close, we can smoothly adjust with playbackRate:
+ // - The video must be playing
+ // - We must be close in time to the server time
+ const playbackRateAdjustment = playbackSmoothing(deltaTime);
+ const adjustedPlaybackRate = Math.max(0, rate - playbackRateAdjustment);
+ if (this.videoElement.playbackRate !== adjustedPlaybackRate) {
+ this.videoElement.playbackRate = adjustedPlaybackRate;
+ }
+ break;
+ }
+ default: {
+ // We cannot smoothly recover:
+ // - We seek just ahead of server time
+ if (this.videoElement.playbackRate !== rate) {
+ this.videoElement.playbackRate = rate;
+ }
+
+ // delay to poll until seeked
+ this.delay = 10;
+ this.seekTo(t + rate * (SEEK_LOOKAHEAD_MS / 1000));
+ break;
+ }
+ }
+ }
+
+ destroy(): void {
+ if (this.videoElement) {
+ this.videoElement.src = '';
+ this.videoElement.remove();
+ }
+ }
+}
diff --git a/packages/javascript/vite.config.ts b/packages/javascript/vite.config.ts
new file mode 100644
index 0000000..ff8b4c5
--- /dev/null
+++ b/packages/javascript/vite.config.ts
@@ -0,0 +1 @@
+export default {};
diff --git a/packages/react/package.json b/packages/react/package.json
index 9586b7b..e0b85af 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -50,4 +50,4 @@
"typescript": "~5.7.2",
"typescript-eslint": "^8.18.1"
}
-}
\ No newline at end of file
+}
diff --git a/packages/timesync/package.json b/packages/timesync/package.json
index 24d01c7..ff8b6a5 100644
--- a/packages/timesync/package.json
+++ b/packages/timesync/package.json
@@ -34,4 +34,4 @@
"typescript-eslint": "^8.18.1",
"vitest": "^4.0.6"
}
-}
\ No newline at end of file
+}
diff --git a/packages/timesync/tsconfig.test.json b/packages/timesync/tsconfig.test.json
deleted file mode 100644
index 11be516..0000000
--- a/packages/timesync/tsconfig.test.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "extends": "./tsconfig.build.json",
- "compilerOptions": {
- // Required for testing with vitest
- "module": "node16",
- "moduleResolution": "node16"
- },
- "include": ["src/**/*.test.ts"]
-}
diff --git a/packages/vite-plugin/package.json b/packages/vite-plugin/package.json
index 1dff315..06afb91 100644
--- a/packages/vite-plugin/package.json
+++ b/packages/vite-plugin/package.json
@@ -54,4 +54,4 @@
"typescript-eslint": "^8.35.1",
"vite": "^6.0.0"
}
-}
\ No newline at end of file
+}
diff --git a/tsconfig.json b/tsconfig.json
index 8362e33..c21801b 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -4,8 +4,8 @@
"skipLibCheck": true,
"declaration": true,
// Target es2019 or higher required to use proper import/export statements between packages
- "target": "es2020",
- "module": "es2020",
- "moduleResolution": "bundler",
+ "target": "es2023",
+ "module": "es2022",
+ "moduleResolution": "bundler"
}
}
diff --git a/yarn.lock b/yarn.lock
index ec16552..bee3826 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -75,16 +75,20 @@ __metadata:
resolution: "@clockworkdog/cogs-client@workspace:packages/javascript"
dependencies:
"@clockworkdog/timesync": "workspace:^"
+ "@cypress/mount-utils": "npm:^4.1.2"
"@eslint/js": "npm:^9.17.0"
"@types/howler": "npm:2.2.12"
"@types/jsdom": "npm:^27"
"@types/node": "npm:^22.10.2"
+ cypress: "npm:^14.5.4"
eslint: "npm:^9.17.0"
eslint-config-prettier: "npm:^9.1.0"
eslint-plugin-prettier: "npm:^5.2.1"
howler: "clockwork-dog/howler.js#fix-looping-clips"
jsdom: "npm:^27.1.0"
prettier: "npm:^3.4.2"
+ react: "npm:^19.1.1"
+ react-dom: "npm:^19.1.1"
reconnecting-websocket: "npm:^4.4.0"
typedoc: "npm:^0.27.5"
typescript: "npm:~5.7.2"
@@ -163,6 +167,49 @@ __metadata:
languageName: node
linkType: hard
+"@cypress/mount-utils@npm:^4.1.2":
+ version: 4.1.2
+ resolution: "@cypress/mount-utils@npm:4.1.2"
+ checksum: 10c0/1c64c3dac4ea25b59487c927c4632161ef8c347735f2812febe7964c4b12c2784791d0ec4d096dc98f5063c445bed8367536aee60fc9d0ecba1fd86ae32087db
+ languageName: node
+ linkType: hard
+
+"@cypress/request@npm:^3.0.9":
+ version: 3.0.9
+ resolution: "@cypress/request@npm:3.0.9"
+ dependencies:
+ aws-sign2: "npm:~0.7.0"
+ aws4: "npm:^1.8.0"
+ caseless: "npm:~0.12.0"
+ combined-stream: "npm:~1.0.6"
+ extend: "npm:~3.0.2"
+ forever-agent: "npm:~0.6.1"
+ form-data: "npm:~4.0.4"
+ http-signature: "npm:~1.4.0"
+ is-typedarray: "npm:~1.0.0"
+ isstream: "npm:~0.1.2"
+ json-stringify-safe: "npm:~5.0.1"
+ mime-types: "npm:~2.1.19"
+ performance-now: "npm:^2.1.0"
+ qs: "npm:6.14.0"
+ safe-buffer: "npm:^5.1.2"
+ tough-cookie: "npm:^5.0.0"
+ tunnel-agent: "npm:^0.6.0"
+ uuid: "npm:^8.3.2"
+ checksum: 10c0/9ebcd3f3d49706e730671bcb0bb86488fe23a2079f12d44b6c762777118fc0286b5ce5c73fb6cacf0ae291fa89a7562ca8a2b43a2486e26906fd84a386ed6967
+ languageName: node
+ linkType: hard
+
+"@cypress/xvfb@npm:^1.2.4":
+ version: 1.2.4
+ resolution: "@cypress/xvfb@npm:1.2.4"
+ dependencies:
+ debug: "npm:^3.1.0"
+ lodash.once: "npm:^4.1.1"
+ checksum: 10c0/1bf6224b244f6093033d77f04f6bef719280542656de063cf8ac3f38957b62aa633e6918af0b9673a8bf0123b42a850db51d9729a3ae3da885ac179bc7fc1d26
+ languageName: node
+ linkType: hard
+
"@esbuild/aix-ppc64@npm:0.25.6":
version: 0.25.6
resolution: "@esbuild/aix-ppc64@npm:0.25.6"
@@ -974,6 +1021,20 @@ __metadata:
languageName: node
linkType: hard
+"@types/sinonjs__fake-timers@npm:8.1.1":
+ version: 8.1.1
+ resolution: "@types/sinonjs__fake-timers@npm:8.1.1"
+ checksum: 10c0/e2e6c425a548177c0930c2f9b82d3951956c9701b9ebf59623d5ad2c3229c523d3c0d598e79fe7392a239657abd3dbe3676be0650ce438bcd1199ee3b617a4d7
+ languageName: node
+ linkType: hard
+
+"@types/sizzle@npm:^2.3.2":
+ version: 2.3.10
+ resolution: "@types/sizzle@npm:2.3.10"
+ checksum: 10c0/d43ec1cd0b5e1f66b1abeaf359608853629cd3d6b8dc8b3b40b85a5ee2ce149a4485ccd7eee5c58b5a2814d384f5a951f1dab5d49041ad83457270cb2bc66fe7
+ languageName: node
+ linkType: hard
+
"@types/tough-cookie@npm:*":
version: 4.0.5
resolution: "@types/tough-cookie@npm:4.0.5"
@@ -997,6 +1058,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/yauzl@npm:^2.9.1":
+ version: 2.10.3
+ resolution: "@types/yauzl@npm:2.10.3"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 10c0/f1b7c1b99fef9f2fe7f1985ef7426d0cebe48cd031f1780fcdc7451eec7e31ac97028f16f50121a59bcf53086a1fc8c856fd5b7d3e00970e43d92ae27d6b43dc
+ languageName: node
+ linkType: hard
+
"@typescript-eslint/eslint-plugin@npm:8.18.1":
version: 8.18.1
resolution: "@typescript-eslint/eslint-plugin@npm:8.18.1"
@@ -1366,6 +1436,16 @@ __metadata:
languageName: node
linkType: hard
+"aggregate-error@npm:^3.0.0":
+ version: 3.1.0
+ resolution: "aggregate-error@npm:3.1.0"
+ dependencies:
+ clean-stack: "npm:^2.0.0"
+ indent-string: "npm:^4.0.0"
+ checksum: 10c0/a42f67faa79e3e6687a4923050e7c9807db3848a037076f791d10e092677d65c1d2d863b7848560699f40fc0502c19f40963fb1cd1fb3d338a7423df8e45e039
+ languageName: node
+ linkType: hard
+
"ajv@npm:^6.12.4":
version: 6.12.6
resolution: "ajv@npm:6.12.6"
@@ -1378,6 +1458,22 @@ __metadata:
languageName: node
linkType: hard
+"ansi-colors@npm:^4.1.1":
+ version: 4.1.3
+ resolution: "ansi-colors@npm:4.1.3"
+ checksum: 10c0/ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9
+ languageName: node
+ linkType: hard
+
+"ansi-escapes@npm:^4.3.0":
+ version: 4.3.2
+ resolution: "ansi-escapes@npm:4.3.2"
+ dependencies:
+ type-fest: "npm:^0.21.3"
+ checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50
+ languageName: node
+ linkType: hard
+
"ansi-regex@npm:^5.0.1":
version: 5.0.1
resolution: "ansi-regex@npm:5.0.1"
@@ -1415,6 +1511,13 @@ __metadata:
languageName: node
linkType: hard
+"arch@npm:^2.2.0":
+ version: 2.2.0
+ resolution: "arch@npm:2.2.0"
+ checksum: 10c0/4ceaf8d8207817c216ebc4469742052cb0a097bc45d9b7fcd60b7507220da545a28562ab5bdd4dfe87921bb56371a0805da4e10d704e01f93a15f83240f1284c
+ languageName: node
+ linkType: hard
+
"argparse@npm:^2.0.1":
version: 2.0.1
resolution: "argparse@npm:2.0.1"
@@ -1512,6 +1615,22 @@ __metadata:
languageName: node
linkType: hard
+"asn1@npm:~0.2.3":
+ version: 0.2.6
+ resolution: "asn1@npm:0.2.6"
+ dependencies:
+ safer-buffer: "npm:~2.1.0"
+ checksum: 10c0/00c8a06c37e548762306bcb1488388d2f76c74c36f70c803f0c081a01d3bdf26090fc088cd812afc5e56a6d49e33765d451a5f8a68ab9c2b087eba65d2e980e0
+ languageName: node
+ linkType: hard
+
+"assert-plus@npm:1.0.0, assert-plus@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "assert-plus@npm:1.0.0"
+ checksum: 10c0/b194b9d50c3a8f872ee85ab110784911e696a4d49f7ee6fc5fb63216dedbefd2c55999c70cb2eaeb4cf4a0e0338b44e9ace3627117b5bf0d42460e9132f21b91
+ languageName: node
+ linkType: hard
+
"assertion-error@npm:^2.0.1":
version: 2.0.1
resolution: "assertion-error@npm:2.0.1"
@@ -1519,6 +1638,34 @@ __metadata:
languageName: node
linkType: hard
+"astral-regex@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "astral-regex@npm:2.0.0"
+ checksum: 10c0/f63d439cc383db1b9c5c6080d1e240bd14dae745f15d11ec5da863e182bbeca70df6c8191cffef5deba0b566ef98834610a68be79ac6379c95eeb26e1b310e25
+ languageName: node
+ linkType: hard
+
+"async@npm:^3.2.0":
+ version: 3.2.6
+ resolution: "async@npm:3.2.6"
+ checksum: 10c0/36484bb15ceddf07078688d95e27076379cc2f87b10c03b6dd8a83e89475a3c8df5848859dd06a4c95af1e4c16fc973de0171a77f18ea00be899aca2a4f85e70
+ languageName: node
+ linkType: hard
+
+"asynckit@npm:^0.4.0":
+ version: 0.4.0
+ resolution: "asynckit@npm:0.4.0"
+ checksum: 10c0/d73e2ddf20c4eb9337e1b3df1a0f6159481050a5de457c55b14ea2e5cb6d90bb69e004c9af54737a5ee0917fcf2c9e25de67777bbe58261847846066ba75bc9d
+ languageName: node
+ linkType: hard
+
+"at-least-node@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "at-least-node@npm:1.0.0"
+ checksum: 10c0/4c058baf6df1bc5a1697cf182e2029c58cd99975288a13f9e70068ef5d6f4e1f1fd7c4d2c3c4912eae44797d1725be9700995736deca441b39f3e66d8dee97ef
+ languageName: node
+ linkType: hard
+
"available-typed-arrays@npm:^1.0.7":
version: 1.0.7
resolution: "available-typed-arrays@npm:1.0.7"
@@ -1528,6 +1675,20 @@ __metadata:
languageName: node
linkType: hard
+"aws-sign2@npm:~0.7.0":
+ version: 0.7.0
+ resolution: "aws-sign2@npm:0.7.0"
+ checksum: 10c0/021d2cc5547d4d9ef1633e0332e746a6f447997758b8b68d6fb33f290986872d2bff5f0c37d5832f41a7229361f093cd81c40898d96ed153493c0fb5cd8575d2
+ languageName: node
+ linkType: hard
+
+"aws4@npm:^1.8.0":
+ version: 1.13.2
+ resolution: "aws4@npm:1.13.2"
+ checksum: 10c0/c993d0d186d699f685d73113733695d648ec7d4b301aba2e2a559d0cd9c1c902308cc52f4095e1396b23fddbc35113644e7f0a6a32753636306e41e3ed6f1e79
+ languageName: node
+ linkType: hard
+
"balanced-match@npm:^1.0.0":
version: 1.0.2
resolution: "balanced-match@npm:1.0.2"
@@ -1535,6 +1696,22 @@ __metadata:
languageName: node
linkType: hard
+"base64-js@npm:^1.3.1":
+ version: 1.5.1
+ resolution: "base64-js@npm:1.5.1"
+ checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf
+ languageName: node
+ linkType: hard
+
+"bcrypt-pbkdf@npm:^1.0.0":
+ version: 1.0.2
+ resolution: "bcrypt-pbkdf@npm:1.0.2"
+ dependencies:
+ tweetnacl: "npm:^0.14.3"
+ checksum: 10c0/ddfe85230b32df25aeebfdccfbc61d3bc493ace49c884c9c68575de1f5dcf733a5d7de9def3b0f318b786616b8d85bad50a28b1da1750c43e0012c93badcc148
+ languageName: node
+ linkType: hard
+
"bidi-js@npm:^1.0.3":
version: 1.0.3
resolution: "bidi-js@npm:1.0.3"
@@ -1544,6 +1721,20 @@ __metadata:
languageName: node
linkType: hard
+"blob-util@npm:^2.0.2":
+ version: 2.0.2
+ resolution: "blob-util@npm:2.0.2"
+ checksum: 10c0/ed82d587827e5c86be122301a7c250f8364963e9582f72a826255bfbd32f8d69cc10169413d666667bb1c4fc8061329ae89d176ffe46fee8f32080af944ccddc
+ languageName: node
+ linkType: hard
+
+"bluebird@npm:^3.7.2":
+ version: 3.7.2
+ resolution: "bluebird@npm:3.7.2"
+ checksum: 10c0/680de03adc54ff925eaa6c7bb9a47a0690e8b5de60f4792604aae8ed618c65e6b63a7893b57ca924beaf53eee69c5af4f8314148c08124c550fe1df1add897d2
+ languageName: node
+ linkType: hard
+
"brace-expansion@npm:^1.1.7":
version: 1.1.11
resolution: "brace-expansion@npm:1.1.11"
@@ -1572,6 +1763,23 @@ __metadata:
languageName: node
linkType: hard
+"buffer-crc32@npm:~0.2.3":
+ version: 0.2.13
+ resolution: "buffer-crc32@npm:0.2.13"
+ checksum: 10c0/cb0a8ddf5cf4f766466db63279e47761eb825693eeba6a5a95ee4ec8cb8f81ede70aa7f9d8aeec083e781d47154290eb5d4d26b3f7a465ec57fb9e7d59c47150
+ languageName: node
+ linkType: hard
+
+"buffer@npm:^5.7.1":
+ version: 5.7.1
+ resolution: "buffer@npm:5.7.1"
+ dependencies:
+ base64-js: "npm:^1.3.1"
+ ieee754: "npm:^1.1.13"
+ checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e
+ languageName: node
+ linkType: hard
+
"bundle-require@npm:^5.1.0":
version: 5.1.0
resolution: "bundle-require@npm:5.1.0"
@@ -1610,6 +1818,13 @@ __metadata:
languageName: node
linkType: hard
+"cachedir@npm:^2.3.0":
+ version: 2.4.0
+ resolution: "cachedir@npm:2.4.0"
+ checksum: 10c0/76bff9009f2c446cd3777a4aede99af634a89670a67012b8041f65e951d3d36cefe8940341ea80c72219ee9913fa1f6146824cd9dfe9874a4bded728af7e6d76
+ languageName: node
+ linkType: hard
+
"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1":
version: 1.0.1
resolution: "call-bind-apply-helpers@npm:1.0.1"
@@ -1649,6 +1864,13 @@ __metadata:
languageName: node
linkType: hard
+"caseless@npm:~0.12.0":
+ version: 0.12.0
+ resolution: "caseless@npm:0.12.0"
+ checksum: 10c0/ccf64bcb6c0232cdc5b7bd91ddd06e23a4b541f138336d4725233ac538041fb2f29c2e86c3c4a7a61ef990b665348db23a047060b9414c3a6603e9fa61ad4626
+ languageName: node
+ linkType: hard
+
"chai@npm:^6.0.1":
version: 6.2.0
resolution: "chai@npm:6.2.0"
@@ -1656,7 +1878,7 @@ __metadata:
languageName: node
linkType: hard
-"chalk@npm:^4.0.0":
+"chalk@npm:^4.0.0, chalk@npm:^4.1.0":
version: 4.1.2
resolution: "chalk@npm:4.1.2"
dependencies:
@@ -1666,6 +1888,13 @@ __metadata:
languageName: node
linkType: hard
+"check-more-types@npm:^2.24.0":
+ version: 2.24.0
+ resolution: "check-more-types@npm:2.24.0"
+ checksum: 10c0/93fda2c32eb5f6cd1161a84a2f4107c0e00b40a851748516791dd9a0992b91bdf504e3bf6bf7673ce603ae620042e11ed4084d16d6d92b36818abc9c2e725520
+ languageName: node
+ linkType: hard
+
"chokidar@npm:^4.0.3":
version: 4.0.3
resolution: "chokidar@npm:4.0.3"
@@ -1682,6 +1911,52 @@ __metadata:
languageName: node
linkType: hard
+"ci-info@npm:^4.1.0":
+ version: 4.3.1
+ resolution: "ci-info@npm:4.3.1"
+ checksum: 10c0/7dd82000f514d76ddfe7775e4cb0d66e5c638f5fa0e2a3be29557e898da0d32ac04f231217d414d07fb968b1fbc6d980ee17ddde0d2c516f23da9cfff608f6c1
+ languageName: node
+ linkType: hard
+
+"clean-stack@npm:^2.0.0":
+ version: 2.2.0
+ resolution: "clean-stack@npm:2.2.0"
+ checksum: 10c0/1f90262d5f6230a17e27d0c190b09d47ebe7efdd76a03b5a1127863f7b3c9aec4c3e6c8bb3a7bbf81d553d56a1fd35728f5a8ef4c63f867ac8d690109742a8c1
+ languageName: node
+ linkType: hard
+
+"cli-cursor@npm:^3.1.0":
+ version: 3.1.0
+ resolution: "cli-cursor@npm:3.1.0"
+ dependencies:
+ restore-cursor: "npm:^3.1.0"
+ checksum: 10c0/92a2f98ff9037d09be3dfe1f0d749664797fb674bf388375a2207a1203b69d41847abf16434203e0089212479e47a358b13a0222ab9fccfe8e2644a7ccebd111
+ languageName: node
+ linkType: hard
+
+"cli-table3@npm:0.6.1":
+ version: 0.6.1
+ resolution: "cli-table3@npm:0.6.1"
+ dependencies:
+ colors: "npm:1.4.0"
+ string-width: "npm:^4.2.0"
+ dependenciesMeta:
+ colors:
+ optional: true
+ checksum: 10c0/19ab1bb14bd11b3ca3557ce5ad37ef73e489ea814b99f803171e6ac0a3f2ae5fffb6dbc8864e33cdcf2a3644ebc31b488b8e624fd74af44a1c77cc365c143db4
+ languageName: node
+ linkType: hard
+
+"cli-truncate@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "cli-truncate@npm:2.1.0"
+ dependencies:
+ slice-ansi: "npm:^3.0.0"
+ string-width: "npm:^4.2.0"
+ checksum: 10c0/dfaa3df675bcef7a3254773de768712b590250420345a4c7ac151f041a4bacb4c25864b1377bee54a39b5925a030c00eabf014e312e3a4ac130952ed3b3879e9
+ languageName: node
+ linkType: hard
+
"cogs-sdk@workspace:.":
version: 0.0.0-use.local
resolution: "cogs-sdk@workspace:."
@@ -1708,6 +1983,29 @@ __metadata:
languageName: node
linkType: hard
+"colorette@npm:^2.0.16":
+ version: 2.0.20
+ resolution: "colorette@npm:2.0.20"
+ checksum: 10c0/e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40
+ languageName: node
+ linkType: hard
+
+"colors@npm:1.4.0":
+ version: 1.4.0
+ resolution: "colors@npm:1.4.0"
+ checksum: 10c0/9af357c019da3c5a098a301cf64e3799d27549d8f185d86f79af23069e4f4303110d115da98483519331f6fb71c8568d5688fa1c6523600044fd4a54e97c4efb
+ languageName: node
+ linkType: hard
+
+"combined-stream@npm:^1.0.8, combined-stream@npm:~1.0.6":
+ version: 1.0.8
+ resolution: "combined-stream@npm:1.0.8"
+ dependencies:
+ delayed-stream: "npm:~1.0.0"
+ checksum: 10c0/0dbb829577e1b1e839fa82b40c07ffaf7de8a09b935cadd355a73652ae70a88b4320db322f6634a4ad93424292fa80973ac6480986247f1734a1137debf271d5
+ languageName: node
+ linkType: hard
+
"commander@npm:^4.0.0":
version: 4.1.1
resolution: "commander@npm:4.1.1"
@@ -1715,6 +2013,20 @@ __metadata:
languageName: node
linkType: hard
+"commander@npm:^6.2.1":
+ version: 6.2.1
+ resolution: "commander@npm:6.2.1"
+ checksum: 10c0/85748abd9d18c8bc88febed58b98f66b7c591d9b5017cad459565761d7b29ca13b7783ea2ee5ce84bf235897333706c4ce29adf1ce15c8252780e7000e2ce9ea
+ languageName: node
+ linkType: hard
+
+"common-tags@npm:^1.8.0":
+ version: 1.8.2
+ resolution: "common-tags@npm:1.8.2"
+ checksum: 10c0/23efe47ff0a1a7c91489271b3a1e1d2a171c12ec7f9b35b29b2fce51270124aff0ec890087e2bc2182c1cb746e232ab7561aaafe05f1e7452aea733d2bfe3f63
+ languageName: node
+ linkType: hard
+
"concat-map@npm:0.0.1":
version: 0.0.1
resolution: "concat-map@npm:0.0.1"
@@ -1736,6 +2048,13 @@ __metadata:
languageName: node
linkType: hard
+"core-util-is@npm:1.0.2":
+ version: 1.0.2
+ resolution: "core-util-is@npm:1.0.2"
+ checksum: 10c0/980a37a93956d0de8a828ce508f9b9e3317039d68922ca79995421944146700e4aaf490a6dbfebcb1c5292a7184600c7710b957d724be1e37b8254c6bc0fe246
+ languageName: node
+ linkType: hard
+
"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.6":
version: 7.0.6
resolution: "cross-spawn@npm:7.0.6"
@@ -1775,6 +2094,69 @@ __metadata:
languageName: node
linkType: hard
+"cypress@npm:^14.5.4":
+ version: 14.5.4
+ resolution: "cypress@npm:14.5.4"
+ dependencies:
+ "@cypress/request": "npm:^3.0.9"
+ "@cypress/xvfb": "npm:^1.2.4"
+ "@types/sinonjs__fake-timers": "npm:8.1.1"
+ "@types/sizzle": "npm:^2.3.2"
+ arch: "npm:^2.2.0"
+ blob-util: "npm:^2.0.2"
+ bluebird: "npm:^3.7.2"
+ buffer: "npm:^5.7.1"
+ cachedir: "npm:^2.3.0"
+ chalk: "npm:^4.1.0"
+ check-more-types: "npm:^2.24.0"
+ ci-info: "npm:^4.1.0"
+ cli-cursor: "npm:^3.1.0"
+ cli-table3: "npm:0.6.1"
+ commander: "npm:^6.2.1"
+ common-tags: "npm:^1.8.0"
+ dayjs: "npm:^1.10.4"
+ debug: "npm:^4.3.4"
+ enquirer: "npm:^2.3.6"
+ eventemitter2: "npm:6.4.7"
+ execa: "npm:4.1.0"
+ executable: "npm:^4.1.1"
+ extract-zip: "npm:2.0.1"
+ figures: "npm:^3.2.0"
+ fs-extra: "npm:^9.1.0"
+ getos: "npm:^3.2.1"
+ hasha: "npm:5.2.2"
+ is-installed-globally: "npm:~0.4.0"
+ lazy-ass: "npm:^1.6.0"
+ listr2: "npm:^3.8.3"
+ lodash: "npm:^4.17.21"
+ log-symbols: "npm:^4.0.0"
+ minimist: "npm:^1.2.8"
+ ospath: "npm:^1.2.2"
+ pretty-bytes: "npm:^5.6.0"
+ process: "npm:^0.11.10"
+ proxy-from-env: "npm:1.0.0"
+ request-progress: "npm:^3.0.0"
+ semver: "npm:^7.7.1"
+ supports-color: "npm:^8.1.1"
+ tmp: "npm:~0.2.3"
+ tree-kill: "npm:1.2.2"
+ untildify: "npm:^4.0.0"
+ yauzl: "npm:^2.10.0"
+ bin:
+ cypress: bin/cypress
+ checksum: 10c0/e4ded8f0ae8a6c56ac9ee615fc62d4b5c6543634035edaa5d5cbd67d6cd45457eef02a67ac90d0aa6f4fbfe25663513f782a6351f9305fd572e89a3ef587d3ab
+ languageName: node
+ linkType: hard
+
+"dashdash@npm:^1.12.0":
+ version: 1.14.1
+ resolution: "dashdash@npm:1.14.1"
+ dependencies:
+ assert-plus: "npm:^1.0.0"
+ checksum: 10c0/64589a15c5bd01fa41ff7007e0f2c6552c5ef2028075daa16b188a3721f4ba001841bf306dfc2eee6e2e6e7f76b38f5f17fb21fa847504192290ffa9e150118a
+ languageName: node
+ linkType: hard
+
"data-urls@npm:^6.0.0":
version: 6.0.0
resolution: "data-urls@npm:6.0.0"
@@ -1818,6 +2200,13 @@ __metadata:
languageName: node
linkType: hard
+"dayjs@npm:^1.10.4":
+ version: 1.11.19
+ resolution: "dayjs@npm:1.11.19"
+ checksum: 10c0/7d8a6074a343f821f81ea284d700bd34ea6c7abbe8d93bce7aba818948957c1b7f56131702e5e890a5622cdfc05dcebe8aed0b8313bdc6838a594d7846b0b000
+ languageName: node
+ linkType: hard
+
"debug@npm:4, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
version: 4.4.0
resolution: "debug@npm:4.4.0"
@@ -1830,27 +2219,36 @@ __metadata:
languageName: node
linkType: hard
-"debug@npm:^4.4.0":
- version: 4.4.1
- resolution: "debug@npm:4.4.1"
+"debug@npm:^3.1.0":
+ version: 3.2.7
+ resolution: "debug@npm:3.2.7"
+ dependencies:
+ ms: "npm:^2.1.1"
+ checksum: 10c0/37d96ae42cbc71c14844d2ae3ba55adf462ec89fd3a999459dec3833944cd999af6007ff29c780f1c61153bcaaf2c842d1e4ce1ec621e4fc4923244942e4a02a
+ languageName: node
+ linkType: hard
+
+"debug@npm:^4.1.1, debug@npm:^4.4.3":
+ version: 4.4.3
+ resolution: "debug@npm:4.4.3"
dependencies:
ms: "npm:^2.1.3"
peerDependenciesMeta:
supports-color:
optional: true
- checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55
+ checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6
languageName: node
linkType: hard
-"debug@npm:^4.4.3":
- version: 4.4.3
- resolution: "debug@npm:4.4.3"
+"debug@npm:^4.4.0":
+ version: 4.4.1
+ resolution: "debug@npm:4.4.1"
dependencies:
ms: "npm:^2.1.3"
peerDependenciesMeta:
supports-color:
optional: true
- checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6
+ checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55
languageName: node
linkType: hard
@@ -1890,6 +2288,13 @@ __metadata:
languageName: node
linkType: hard
+"delayed-stream@npm:~1.0.0":
+ version: 1.0.0
+ resolution: "delayed-stream@npm:1.0.0"
+ checksum: 10c0/d758899da03392e6712f042bec80aa293bbe9e9ff1b2634baae6a360113e708b91326594c8a486d475c69d6259afb7efacdc3537bfcda1c6c648e390ce601b19
+ languageName: node
+ linkType: hard
+
"doctrine@npm:^2.1.0":
version: 2.1.0
resolution: "doctrine@npm:2.1.0"
@@ -1917,6 +2322,16 @@ __metadata:
languageName: node
linkType: hard
+"ecc-jsbn@npm:~0.1.1":
+ version: 0.1.2
+ resolution: "ecc-jsbn@npm:0.1.2"
+ dependencies:
+ jsbn: "npm:~0.1.0"
+ safer-buffer: "npm:^2.1.0"
+ checksum: 10c0/6cf168bae1e2dad2e46561d9af9cbabfbf5ff592176ad4e9f0f41eaaf5fe5e10bb58147fe0a804de62b1ee9dad42c28810c88d652b21b6013c47ba8efa274ca1
+ languageName: node
+ linkType: hard
+
"emoji-regex@npm:^8.0.0":
version: 8.0.0
resolution: "emoji-regex@npm:8.0.0"
@@ -1940,6 +2355,25 @@ __metadata:
languageName: node
linkType: hard
+"end-of-stream@npm:^1.1.0":
+ version: 1.4.5
+ resolution: "end-of-stream@npm:1.4.5"
+ dependencies:
+ once: "npm:^1.4.0"
+ checksum: 10c0/b0701c92a10b89afb1cb45bf54a5292c6f008d744eb4382fa559d54775ff31617d1d7bc3ef617575f552e24fad2c7c1a1835948c66b3f3a4be0a6c1f35c883d8
+ languageName: node
+ linkType: hard
+
+"enquirer@npm:^2.3.6":
+ version: 2.4.1
+ resolution: "enquirer@npm:2.4.1"
+ dependencies:
+ ansi-colors: "npm:^4.1.1"
+ strip-ansi: "npm:^6.0.1"
+ checksum: 10c0/43850479d7a51d36a9c924b518dcdc6373b5a8ae3401097d336b7b7e258324749d0ad37a1fcaa5706f04799baa05585cd7af19ebdf7667673e7694435fcea918
+ languageName: node
+ linkType: hard
+
"entities@npm:^4.4.0":
version: 4.5.0
resolution: "entities@npm:4.5.0"
@@ -2088,6 +2522,18 @@ __metadata:
languageName: node
linkType: hard
+"es-set-tostringtag@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "es-set-tostringtag@npm:2.1.0"
+ dependencies:
+ es-errors: "npm:^1.3.0"
+ get-intrinsic: "npm:^1.2.6"
+ has-tostringtag: "npm:^1.0.2"
+ hasown: "npm:^2.0.2"
+ checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af
+ languageName: node
+ linkType: hard
+
"es-shim-unscopables@npm:^1.0.2":
version: 1.0.2
resolution: "es-shim-unscopables@npm:1.0.2"
@@ -2197,6 +2643,13 @@ __metadata:
languageName: node
linkType: hard
+"escape-string-regexp@npm:^1.0.5":
+ version: 1.0.5
+ resolution: "escape-string-regexp@npm:1.0.5"
+ checksum: 10c0/a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371
+ languageName: node
+ linkType: hard
+
"escape-string-regexp@npm:^4.0.0":
version: 4.0.0
resolution: "escape-string-regexp@npm:4.0.0"
@@ -2506,6 +2959,39 @@ __metadata:
languageName: node
linkType: hard
+"eventemitter2@npm:6.4.7":
+ version: 6.4.7
+ resolution: "eventemitter2@npm:6.4.7"
+ checksum: 10c0/35d8e9d51b919114eb072d33786274e1475db50efe00960c24c088ce4f76c07a826ccc927602724928efb3d8f09a7d8dd1fa79e410875118c0e9846959287f34
+ languageName: node
+ linkType: hard
+
+"execa@npm:4.1.0":
+ version: 4.1.0
+ resolution: "execa@npm:4.1.0"
+ dependencies:
+ cross-spawn: "npm:^7.0.0"
+ get-stream: "npm:^5.0.0"
+ human-signals: "npm:^1.1.1"
+ is-stream: "npm:^2.0.0"
+ merge-stream: "npm:^2.0.0"
+ npm-run-path: "npm:^4.0.0"
+ onetime: "npm:^5.1.0"
+ signal-exit: "npm:^3.0.2"
+ strip-final-newline: "npm:^2.0.0"
+ checksum: 10c0/02211601bb1c52710260edcc68fb84c3c030dc68bafc697c90ada3c52cc31375337de8c24826015b8382a58d63569ffd203b79c94fef217d65503e3e8d2c52ba
+ languageName: node
+ linkType: hard
+
+"executable@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "executable@npm:4.1.1"
+ dependencies:
+ pify: "npm:^2.2.0"
+ checksum: 10c0/c3cc5d2d2e3cdb1b7d7b0639ebd5566d113d7ada21cfa07f5226d55ba2a210320116720e07570ed5659ef2ec516bc00c8f0488dac75d112fd324ef25c2100173
+ languageName: node
+ linkType: hard
+
"expect-type@npm:^1.2.2":
version: 1.2.2
resolution: "expect-type@npm:1.2.2"
@@ -2520,6 +3006,44 @@ __metadata:
languageName: node
linkType: hard
+"extend@npm:~3.0.2":
+ version: 3.0.2
+ resolution: "extend@npm:3.0.2"
+ checksum: 10c0/73bf6e27406e80aa3e85b0d1c4fd987261e628064e170ca781125c0b635a3dabad5e05adbf07595ea0cf1e6c5396cacb214af933da7cbaf24fe75ff14818e8f9
+ languageName: node
+ linkType: hard
+
+"extract-zip@npm:2.0.1":
+ version: 2.0.1
+ resolution: "extract-zip@npm:2.0.1"
+ dependencies:
+ "@types/yauzl": "npm:^2.9.1"
+ debug: "npm:^4.1.1"
+ get-stream: "npm:^5.1.0"
+ yauzl: "npm:^2.10.0"
+ dependenciesMeta:
+ "@types/yauzl":
+ optional: true
+ bin:
+ extract-zip: cli.js
+ checksum: 10c0/9afbd46854aa15a857ae0341a63a92743a7b89c8779102c3b4ffc207516b2019337353962309f85c66ee3d9092202a83cdc26dbf449a11981272038443974aee
+ languageName: node
+ linkType: hard
+
+"extsprintf@npm:1.3.0":
+ version: 1.3.0
+ resolution: "extsprintf@npm:1.3.0"
+ checksum: 10c0/f75114a8388f0cbce68e277b6495dc3930db4dde1611072e4a140c24e204affd77320d004b947a132e9a3b97b8253017b2b62dce661975fb0adced707abf1ab5
+ languageName: node
+ linkType: hard
+
+"extsprintf@npm:^1.2.0":
+ version: 1.4.1
+ resolution: "extsprintf@npm:1.4.1"
+ checksum: 10c0/e10e2769985d0e9b6c7199b053a9957589d02e84de42832c295798cb422a025e6d4a92e0259c1fb4d07090f5bfde6b55fd9f880ac5855bd61d775f8ab75a7ab0
+ languageName: node
+ linkType: hard
+
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
version: 3.1.3
resolution: "fast-deep-equal@npm:3.1.3"
@@ -2570,6 +3094,15 @@ __metadata:
languageName: node
linkType: hard
+"fd-slicer@npm:~1.1.0":
+ version: 1.1.0
+ resolution: "fd-slicer@npm:1.1.0"
+ dependencies:
+ pend: "npm:~1.2.0"
+ checksum: 10c0/304dd70270298e3ffe3bcc05e6f7ade2511acc278bc52d025f8918b48b6aa3b77f10361bddfadfe2a28163f7af7adbdce96f4d22c31b2f648ba2901f0c5fc20e
+ languageName: node
+ linkType: hard
+
"fdir@npm:^6.4.4":
version: 6.4.6
resolution: "fdir@npm:6.4.6"
@@ -2594,6 +3127,15 @@ __metadata:
languageName: node
linkType: hard
+"figures@npm:^3.2.0":
+ version: 3.2.0
+ resolution: "figures@npm:3.2.0"
+ dependencies:
+ escape-string-regexp: "npm:^1.0.5"
+ checksum: 10c0/9c421646ede432829a50bc4e55c7a4eb4bcb7cc07b5bab2f471ef1ab9a344595bbebb6c5c21470093fbb730cd81bbca119624c40473a125293f656f49cb47629
+ languageName: node
+ linkType: hard
+
"file-entry-cache@npm:^8.0.0":
version: 8.0.0
resolution: "file-entry-cache@npm:8.0.0"
@@ -2669,6 +3211,38 @@ __metadata:
languageName: node
linkType: hard
+"forever-agent@npm:~0.6.1":
+ version: 0.6.1
+ resolution: "forever-agent@npm:0.6.1"
+ checksum: 10c0/364f7f5f7d93ab661455351ce116a67877b66f59aca199559a999bd39e3cfadbfbfacc10415a915255e2210b30c23febe9aec3ca16bf2d1ff11c935a1000e24c
+ languageName: node
+ linkType: hard
+
+"form-data@npm:~4.0.4":
+ version: 4.0.4
+ resolution: "form-data@npm:4.0.4"
+ dependencies:
+ asynckit: "npm:^0.4.0"
+ combined-stream: "npm:^1.0.8"
+ es-set-tostringtag: "npm:^2.1.0"
+ hasown: "npm:^2.0.2"
+ mime-types: "npm:^2.1.12"
+ checksum: 10c0/373525a9a034b9d57073e55eab79e501a714ffac02e7a9b01be1c820780652b16e4101819785e1e18f8d98f0aee866cc654d660a435c378e16a72f2e7cac9695
+ languageName: node
+ linkType: hard
+
+"fs-extra@npm:^9.1.0":
+ version: 9.1.0
+ resolution: "fs-extra@npm:9.1.0"
+ dependencies:
+ at-least-node: "npm:^1.0.0"
+ graceful-fs: "npm:^4.2.0"
+ jsonfile: "npm:^6.0.1"
+ universalify: "npm:^2.0.0"
+ checksum: 10c0/9b808bd884beff5cb940773018179a6b94a966381d005479f00adda6b44e5e3d4abf765135773d849cc27efe68c349e4a7b86acd7d3306d5932c14f3a4b17a92
+ languageName: node
+ linkType: hard
+
"fs-minipass@npm:^3.0.0":
version: 3.0.3
resolution: "fs-minipass@npm:3.0.3"
@@ -2742,6 +3316,15 @@ __metadata:
languageName: node
linkType: hard
+"get-stream@npm:^5.0.0, get-stream@npm:^5.1.0":
+ version: 5.2.0
+ resolution: "get-stream@npm:5.2.0"
+ dependencies:
+ pump: "npm:^3.0.0"
+ checksum: 10c0/43797ffd815fbb26685bf188c8cfebecb8af87b3925091dd7b9a9c915993293d78e3c9e1bce125928ff92f2d0796f3889b92b5ec6d58d1041b574682132e0a80
+ languageName: node
+ linkType: hard
+
"get-symbol-description@npm:^1.0.2":
version: 1.0.2
resolution: "get-symbol-description@npm:1.0.2"
@@ -2753,6 +3336,24 @@ __metadata:
languageName: node
linkType: hard
+"getos@npm:^3.2.1":
+ version: 3.2.1
+ resolution: "getos@npm:3.2.1"
+ dependencies:
+ async: "npm:^3.2.0"
+ checksum: 10c0/21556fca1da4dfc8f1707261b4f9ff19b9e9bfefa76478249d2abddba3cd014bd6c5360634add1590b27e0b27d422e8f997dddaa0234aae1fa4c54f33f82e841
+ languageName: node
+ linkType: hard
+
+"getpass@npm:^0.1.1":
+ version: 0.1.7
+ resolution: "getpass@npm:0.1.7"
+ dependencies:
+ assert-plus: "npm:^1.0.0"
+ checksum: 10c0/c13f8530ecf16fc509f3fa5cd8dd2129ffa5d0c7ccdf5728b6022d52954c2d24be3706b4cdf15333eec52f1fbb43feb70a01dabc639d1d10071e371da8aaa52f
+ languageName: node
+ linkType: hard
+
"glob-parent@npm:^5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
@@ -2787,6 +3388,15 @@ __metadata:
languageName: node
linkType: hard
+"global-dirs@npm:^3.0.0":
+ version: 3.0.1
+ resolution: "global-dirs@npm:3.0.1"
+ dependencies:
+ ini: "npm:2.0.0"
+ checksum: 10c0/ef65e2241a47ff978f7006a641302bc7f4c03dfb98783d42bf7224c136e3a06df046e70ee3a010cf30214114755e46c9eb5eb1513838812fbbe0d92b14c25080
+ languageName: node
+ linkType: hard
+
"globals@npm:^14.0.0":
version: 14.0.0
resolution: "globals@npm:14.0.0"
@@ -2825,7 +3435,7 @@ __metadata:
languageName: node
linkType: hard
-"graceful-fs@npm:^4.2.6":
+"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6":
version: 4.2.11
resolution: "graceful-fs@npm:4.2.11"
checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2
@@ -2887,6 +3497,16 @@ __metadata:
languageName: node
linkType: hard
+"hasha@npm:5.2.2":
+ version: 5.2.2
+ resolution: "hasha@npm:5.2.2"
+ dependencies:
+ is-stream: "npm:^2.0.0"
+ type-fest: "npm:^0.8.0"
+ checksum: 10c0/9d10d4e665a37beea6e18ba3a0c0399a05b26e505c5ff2fe9115b64fedb3ca95f68c89cf15b08ee4d09fd3064b5e1bfc8e8247353c7aa6b7388471d0f86dca74
+ languageName: node
+ linkType: hard
+
"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2":
version: 2.0.2
resolution: "hasown@npm:2.0.2"
@@ -2929,6 +3549,17 @@ __metadata:
languageName: node
linkType: hard
+"http-signature@npm:~1.4.0":
+ version: 1.4.0
+ resolution: "http-signature@npm:1.4.0"
+ dependencies:
+ assert-plus: "npm:^1.0.0"
+ jsprim: "npm:^2.0.2"
+ sshpk: "npm:^1.18.0"
+ checksum: 10c0/b9806f5a9ed82a146589837d175c43b596b1cc8c9431665e83d47c152aa8a4629dd1b1e050f8f56e7f17f62cf97b58e888775093310441ddee5f105f28646b2b
+ languageName: node
+ linkType: hard
+
"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6":
version: 7.0.6
resolution: "https-proxy-agent@npm:7.0.6"
@@ -2939,6 +3570,13 @@ __metadata:
languageName: node
linkType: hard
+"human-signals@npm:^1.1.1":
+ version: 1.1.1
+ resolution: "human-signals@npm:1.1.1"
+ checksum: 10c0/18810ed239a7a5e23fb6c32d0fd4be75d7cd337a07ad59b8dbf0794cb0761e6e628349ee04c409e605fe55344716eab5d0a47a62ba2a2d0d367c89a2b4247b1e
+ languageName: node
+ linkType: hard
+
"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
version: 0.6.3
resolution: "iconv-lite@npm:0.6.3"
@@ -2948,6 +3586,13 @@ __metadata:
languageName: node
linkType: hard
+"ieee754@npm:^1.1.13":
+ version: 1.2.1
+ resolution: "ieee754@npm:1.2.1"
+ checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb
+ languageName: node
+ linkType: hard
+
"ignore@npm:^5.2.0, ignore@npm:^5.3.1":
version: 5.3.2
resolution: "ignore@npm:5.3.2"
@@ -2979,6 +3624,20 @@ __metadata:
languageName: node
linkType: hard
+"indent-string@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "indent-string@npm:4.0.0"
+ checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f
+ languageName: node
+ linkType: hard
+
+"ini@npm:2.0.0":
+ version: 2.0.0
+ resolution: "ini@npm:2.0.0"
+ checksum: 10c0/2e0c8f386369139029da87819438b20a1ff3fe58372d93fb1a86e9d9344125ace3a806b8ec4eb160a46e64cbc422fe68251869441676af49b7fc441af2389c25
+ languageName: node
+ linkType: hard
+
"internal-slot@npm:^1.0.7, internal-slot@npm:^1.1.0":
version: 1.1.0
resolution: "internal-slot@npm:1.1.0"
@@ -3117,6 +3776,16 @@ __metadata:
languageName: node
linkType: hard
+"is-installed-globally@npm:~0.4.0":
+ version: 0.4.0
+ resolution: "is-installed-globally@npm:0.4.0"
+ dependencies:
+ global-dirs: "npm:^3.0.0"
+ is-path-inside: "npm:^3.0.2"
+ checksum: 10c0/f3e6220ee5824b845c9ed0d4b42c24272701f1f9926936e30c0e676254ca5b34d1b92c6205cae11b283776f9529212c0cdabb20ec280a6451677d6493ca9c22d
+ languageName: node
+ linkType: hard
+
"is-map@npm:^2.0.3":
version: 2.0.3
resolution: "is-map@npm:2.0.3"
@@ -3148,6 +3817,13 @@ __metadata:
languageName: node
linkType: hard
+"is-path-inside@npm:^3.0.2":
+ version: 3.0.3
+ resolution: "is-path-inside@npm:3.0.3"
+ checksum: 10c0/cf7d4ac35fb96bab6a1d2c3598fe5ebb29aafb52c0aaa482b5a3ed9d8ba3edc11631e3ec2637660c44b3ce0e61a08d54946e8af30dec0b60a7c27296c68ffd05
+ languageName: node
+ linkType: hard
+
"is-potential-custom-element-name@npm:^1.0.1":
version: 1.0.1
resolution: "is-potential-custom-element-name@npm:1.0.1"
@@ -3183,6 +3859,13 @@ __metadata:
languageName: node
linkType: hard
+"is-stream@npm:^2.0.0":
+ version: 2.0.1
+ resolution: "is-stream@npm:2.0.1"
+ checksum: 10c0/7c284241313fc6efc329b8d7f08e16c0efeb6baab1b4cd0ba579eb78e5af1aa5da11e68559896a2067cd6c526bd29241dda4eb1225e627d5aa1a89a76d4635a5
+ languageName: node
+ linkType: hard
+
"is-string@npm:^1.0.7, is-string@npm:^1.1.1":
version: 1.1.1
resolution: "is-string@npm:1.1.1"
@@ -3213,6 +3896,20 @@ __metadata:
languageName: node
linkType: hard
+"is-typedarray@npm:~1.0.0":
+ version: 1.0.0
+ resolution: "is-typedarray@npm:1.0.0"
+ checksum: 10c0/4c096275ba041a17a13cca33ac21c16bc4fd2d7d7eb94525e7cd2c2f2c1a3ab956e37622290642501ff4310601e413b675cf399ad6db49855527d2163b3eeeec
+ languageName: node
+ linkType: hard
+
+"is-unicode-supported@npm:^0.1.0":
+ version: 0.1.0
+ resolution: "is-unicode-supported@npm:0.1.0"
+ checksum: 10c0/00cbe3455c3756be68d2542c416cab888aebd5012781d6819749fefb15162ff23e38501fe681b3d751c73e8ff561ac09a5293eba6f58fdf0178462ce6dcb3453
+ languageName: node
+ linkType: hard
+
"is-weakmap@npm:^2.0.2":
version: 2.0.2
resolution: "is-weakmap@npm:2.0.2"
@@ -3260,6 +3957,13 @@ __metadata:
languageName: node
linkType: hard
+"isstream@npm:~0.1.2":
+ version: 0.1.2
+ resolution: "isstream@npm:0.1.2"
+ checksum: 10c0/a6686a878735ca0a48e0d674dd6d8ad31aedfaf70f07920da16ceadc7577b46d67179a60b313f2e6860cb097a2c2eb3cbd0b89e921ae89199a59a17c3273d66f
+ languageName: node
+ linkType: hard
+
"iterator.prototype@npm:^1.1.3":
version: 1.1.4
resolution: "iterator.prototype@npm:1.1.4"
@@ -3319,6 +4023,13 @@ __metadata:
languageName: node
linkType: hard
+"jsbn@npm:~0.1.0":
+ version: 0.1.1
+ resolution: "jsbn@npm:0.1.1"
+ checksum: 10c0/e046e05c59ff880ee4ef68902dbdcb6d2f3c5d60c357d4d68647dc23add556c31c0e5f41bdb7e69e793dd63468bd9e085da3636341048ef577b18f5b713877c0
+ languageName: node
+ linkType: hard
+
"jsdom@npm:^27.1.0":
version: 27.1.0
resolution: "jsdom@npm:27.1.0"
@@ -3366,6 +4077,13 @@ __metadata:
languageName: node
linkType: hard
+"json-schema@npm:0.4.0":
+ version: 0.4.0
+ resolution: "json-schema@npm:0.4.0"
+ checksum: 10c0/d4a637ec1d83544857c1c163232f3da46912e971d5bf054ba44fdb88f07d8d359a462b4aec46f2745efbc57053365608d88bc1d7b1729f7b4fc3369765639ed3
+ languageName: node
+ linkType: hard
+
"json-stable-stringify-without-jsonify@npm:^1.0.1":
version: 1.0.1
resolution: "json-stable-stringify-without-jsonify@npm:1.0.1"
@@ -3373,6 +4091,38 @@ __metadata:
languageName: node
linkType: hard
+"json-stringify-safe@npm:~5.0.1":
+ version: 5.0.1
+ resolution: "json-stringify-safe@npm:5.0.1"
+ checksum: 10c0/7dbf35cd0411d1d648dceb6d59ce5857ec939e52e4afc37601aa3da611f0987d5cee5b38d58329ceddf3ed48bd7215229c8d52059ab01f2444a338bf24ed0f37
+ languageName: node
+ linkType: hard
+
+"jsonfile@npm:^6.0.1":
+ version: 6.2.0
+ resolution: "jsonfile@npm:6.2.0"
+ dependencies:
+ graceful-fs: "npm:^4.1.6"
+ universalify: "npm:^2.0.0"
+ dependenciesMeta:
+ graceful-fs:
+ optional: true
+ checksum: 10c0/7f4f43b08d1869ded8a6822213d13ae3b99d651151d77efd1557ced0889c466296a7d9684e397bd126acf5eb2cfcb605808c3e681d0fdccd2fe5a04b47e76c0d
+ languageName: node
+ linkType: hard
+
+"jsprim@npm:^2.0.2":
+ version: 2.0.2
+ resolution: "jsprim@npm:2.0.2"
+ dependencies:
+ assert-plus: "npm:1.0.0"
+ extsprintf: "npm:1.3.0"
+ json-schema: "npm:0.4.0"
+ verror: "npm:1.10.0"
+ checksum: 10c0/677be2d41df536c92c6d0114a492ef197084018cfbb1a3e10b1fa1aad889564b2e3a7baa6af7949cc2d73678f42368b0be165a26bd4e4de6883a30dd6a24e98d
+ languageName: node
+ linkType: hard
+
"jsx-ast-utils@npm:^2.4.1 || ^3.0.0":
version: 3.3.5
resolution: "jsx-ast-utils@npm:3.3.5"
@@ -3394,6 +4144,13 @@ __metadata:
languageName: node
linkType: hard
+"lazy-ass@npm:^1.6.0":
+ version: 1.6.0
+ resolution: "lazy-ass@npm:1.6.0"
+ checksum: 10c0/4af6cb9a333fbc811268c745f9173fba0f99ecb817cc9c0fae5dbf986b797b730ff525504128f6623b91aba32b02124553a34b0d14de3762b637b74d7233f3bd
+ languageName: node
+ linkType: hard
+
"levn@npm:^0.4.1":
version: 0.4.1
resolution: "levn@npm:0.4.1"
@@ -3427,6 +4184,27 @@ __metadata:
languageName: node
linkType: hard
+"listr2@npm:^3.8.3":
+ version: 3.14.0
+ resolution: "listr2@npm:3.14.0"
+ dependencies:
+ cli-truncate: "npm:^2.1.0"
+ colorette: "npm:^2.0.16"
+ log-update: "npm:^4.0.0"
+ p-map: "npm:^4.0.0"
+ rfdc: "npm:^1.3.0"
+ rxjs: "npm:^7.5.1"
+ through: "npm:^2.3.8"
+ wrap-ansi: "npm:^7.0.0"
+ peerDependencies:
+ enquirer: ">= 2.3.0 < 3"
+ peerDependenciesMeta:
+ enquirer:
+ optional: true
+ checksum: 10c0/8301703876ad6bf50cd769e9c1169c2aa435951d69d4f54fc202a13c1b6006a9b3afbcf9842440eb22f08beec4d311d365e31d4ed2e0fcabf198d8085b06a421
+ languageName: node
+ linkType: hard
+
"load-tsconfig@npm:^0.2.3":
version: 0.2.5
resolution: "load-tsconfig@npm:0.2.5"
@@ -3450,6 +4228,13 @@ __metadata:
languageName: node
linkType: hard
+"lodash.once@npm:^4.1.1":
+ version: 4.1.1
+ resolution: "lodash.once@npm:4.1.1"
+ checksum: 10c0/46a9a0a66c45dd812fcc016e46605d85ad599fe87d71a02f6736220554b52ffbe82e79a483ad40f52a8a95755b0d1077fba259da8bfb6694a7abbf4a48f1fc04
+ languageName: node
+ linkType: hard
+
"lodash.sortby@npm:^4.7.0":
version: 4.7.0
resolution: "lodash.sortby@npm:4.7.0"
@@ -3457,6 +4242,35 @@ __metadata:
languageName: node
linkType: hard
+"lodash@npm:^4.17.21":
+ version: 4.17.21
+ resolution: "lodash@npm:4.17.21"
+ checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c
+ languageName: node
+ linkType: hard
+
+"log-symbols@npm:^4.0.0":
+ version: 4.1.0
+ resolution: "log-symbols@npm:4.1.0"
+ dependencies:
+ chalk: "npm:^4.1.0"
+ is-unicode-supported: "npm:^0.1.0"
+ checksum: 10c0/67f445a9ffa76db1989d0fa98586e5bc2fd5247260dafb8ad93d9f0ccd5896d53fb830b0e54dade5ad838b9de2006c826831a3c528913093af20dff8bd24aca6
+ languageName: node
+ linkType: hard
+
+"log-update@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "log-update@npm:4.0.0"
+ dependencies:
+ ansi-escapes: "npm:^4.3.0"
+ cli-cursor: "npm:^3.1.0"
+ slice-ansi: "npm:^4.0.0"
+ wrap-ansi: "npm:^6.2.0"
+ checksum: 10c0/18b299e230432a156f2535660776406d15ba8bb7817dd3eaadd58004b363756d4ecaabcd658f9949f90b62ea7d3354423be3fdeb7a201ab951ec0e8d6139af86
+ languageName: node
+ linkType: hard
+
"loose-envify@npm:^1.4.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"
@@ -3563,6 +4377,13 @@ __metadata:
languageName: node
linkType: hard
+"merge-stream@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "merge-stream@npm:2.0.0"
+ checksum: 10c0/867fdbb30a6d58b011449b8885601ec1690c3e41c759ecd5a9d609094f7aed0096c37823ff4a7190ef0b8f22cc86beb7049196ff68c016e3b3c671d0dac91ce5
+ languageName: node
+ linkType: hard
+
"merge2@npm:^1.3.0":
version: 1.4.1
resolution: "merge2@npm:1.4.1"
@@ -3580,6 +4401,29 @@ __metadata:
languageName: node
linkType: hard
+"mime-db@npm:1.52.0":
+ version: 1.52.0
+ resolution: "mime-db@npm:1.52.0"
+ checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa
+ languageName: node
+ linkType: hard
+
+"mime-types@npm:^2.1.12, mime-types@npm:~2.1.19":
+ version: 2.1.35
+ resolution: "mime-types@npm:2.1.35"
+ dependencies:
+ mime-db: "npm:1.52.0"
+ checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2
+ languageName: node
+ linkType: hard
+
+"mimic-fn@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "mimic-fn@npm:2.1.0"
+ checksum: 10c0/b26f5479d7ec6cc2bce275a08f146cf78f5e7b661b18114e2506dd91ec7ec47e7a25bf4360e5438094db0560bcc868079fb3b1fb3892b833c1ecbf63f80c95a4
+ languageName: node
+ linkType: hard
+
"minimatch@npm:^3.1.2":
version: 3.1.2
resolution: "minimatch@npm:3.1.2"
@@ -3598,6 +4442,13 @@ __metadata:
languageName: node
linkType: hard
+"minimist@npm:^1.2.8":
+ version: 1.2.8
+ resolution: "minimist@npm:1.2.8"
+ checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6
+ languageName: node
+ linkType: hard
+
"minipass-collect@npm:^2.0.1":
version: 2.0.1
resolution: "minipass-collect@npm:2.0.1"
@@ -3696,7 +4547,7 @@ __metadata:
languageName: node
linkType: hard
-"ms@npm:^2.1.3":
+"ms@npm:^2.1.1, ms@npm:^2.1.3":
version: 2.1.3
resolution: "ms@npm:2.1.3"
checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48
@@ -3768,6 +4619,15 @@ __metadata:
languageName: node
linkType: hard
+"npm-run-path@npm:^4.0.0":
+ version: 4.0.1
+ resolution: "npm-run-path@npm:4.0.1"
+ dependencies:
+ path-key: "npm:^3.0.0"
+ checksum: 10c0/6f9353a95288f8455cf64cbeb707b28826a7f29690244c1e4bb61ec573256e021b6ad6651b394eb1ccfd00d6ec50147253aba2c5fe58a57ceb111fad62c519ac
+ languageName: node
+ linkType: hard
+
"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
@@ -3835,6 +4695,24 @@ __metadata:
languageName: node
linkType: hard
+"once@npm:^1.3.1, once@npm:^1.4.0":
+ version: 1.4.0
+ resolution: "once@npm:1.4.0"
+ dependencies:
+ wrappy: "npm:1"
+ checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0
+ languageName: node
+ linkType: hard
+
+"onetime@npm:^5.1.0":
+ version: 5.1.2
+ resolution: "onetime@npm:5.1.2"
+ dependencies:
+ mimic-fn: "npm:^2.1.0"
+ checksum: 10c0/ffcef6fbb2692c3c40749f31ea2e22677a876daea92959b8a80b521d95cca7a668c884d8b2045d1d8ee7d56796aa405c405462af112a1477594cc63531baeb8f
+ languageName: node
+ linkType: hard
+
"optionator@npm:^0.9.3":
version: 0.9.4
resolution: "optionator@npm:0.9.4"
@@ -3849,6 +4727,13 @@ __metadata:
languageName: node
linkType: hard
+"ospath@npm:^1.2.2":
+ version: 1.2.2
+ resolution: "ospath@npm:1.2.2"
+ checksum: 10c0/e485a6ca91964f786163408b093860bf26a9d9704d83ec39ccf463b9f11ea712b780b23b73d1f64536de62c5f66244dd94ed83fc9ffe3c1564dd1eed5cdae923
+ languageName: node
+ linkType: hard
+
"p-limit@npm:^3.0.2":
version: 3.1.0
resolution: "p-limit@npm:3.1.0"
@@ -3867,6 +4752,15 @@ __metadata:
languageName: node
linkType: hard
+"p-map@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "p-map@npm:4.0.0"
+ dependencies:
+ aggregate-error: "npm:^3.0.0"
+ checksum: 10c0/592c05bd6262c466ce269ff172bb8de7c6975afca9b50c975135b974e9bdaafbfe80e61aaaf5be6d1200ba08b30ead04b88cfa7e25ff1e3b93ab28c9f62a2c75
+ languageName: node
+ linkType: hard
+
"p-map@npm:^7.0.2":
version: 7.0.3
resolution: "p-map@npm:7.0.3"
@@ -3915,7 +4809,7 @@ __metadata:
languageName: node
linkType: hard
-"path-key@npm:^3.1.0":
+"path-key@npm:^3.0.0, path-key@npm:^3.1.0":
version: 3.1.1
resolution: "path-key@npm:3.1.1"
checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c
@@ -3946,6 +4840,20 @@ __metadata:
languageName: node
linkType: hard
+"pend@npm:~1.2.0":
+ version: 1.2.0
+ resolution: "pend@npm:1.2.0"
+ checksum: 10c0/8a87e63f7a4afcfb0f9f77b39bb92374afc723418b9cb716ee4257689224171002e07768eeade4ecd0e86f1fa3d8f022994219fb45634f2dbd78c6803e452458
+ languageName: node
+ linkType: hard
+
+"performance-now@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "performance-now@npm:2.1.0"
+ checksum: 10c0/22c54de06f269e29f640e0e075207af57de5052a3d15e360c09b9a8663f393f6f45902006c1e71aa8a5a1cdfb1a47fe268826f8496d6425c362f00f5bc3e85d9
+ languageName: node
+ linkType: hard
+
"picocolors@npm:^1.1.1":
version: 1.1.1
resolution: "picocolors@npm:1.1.1"
@@ -3974,6 +4882,13 @@ __metadata:
languageName: node
linkType: hard
+"pify@npm:^2.2.0":
+ version: 2.3.0
+ resolution: "pify@npm:2.3.0"
+ checksum: 10c0/551ff8ab830b1052633f59cb8adc9ae8407a436e06b4a9718bcb27dc5844b83d535c3a8512b388b6062af65a98c49bdc0dd523d8b2617b188f7c8fee457158dc
+ languageName: node
+ linkType: hard
+
"pirates@npm:^4.0.1":
version: 4.0.7
resolution: "pirates@npm:4.0.7"
@@ -4067,6 +4982,13 @@ __metadata:
languageName: node
linkType: hard
+"pretty-bytes@npm:^5.6.0":
+ version: 5.6.0
+ resolution: "pretty-bytes@npm:5.6.0"
+ checksum: 10c0/f69f494dcc1adda98dbe0e4a36d301e8be8ff99bfde7a637b2ee2820e7cb583b0fc0f3a63b0e3752c01501185a5cf38602c7be60da41bdf84ef5b70e89c370f3
+ languageName: node
+ linkType: hard
+
"proc-log@npm:^5.0.0":
version: 5.0.0
resolution: "proc-log@npm:5.0.0"
@@ -4074,6 +4996,13 @@ __metadata:
languageName: node
linkType: hard
+"process@npm:^0.11.10":
+ version: 0.11.10
+ resolution: "process@npm:0.11.10"
+ checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3
+ languageName: node
+ linkType: hard
+
"promise-retry@npm:^2.0.1":
version: 2.0.1
resolution: "promise-retry@npm:2.0.1"
@@ -4095,6 +5024,23 @@ __metadata:
languageName: node
linkType: hard
+"proxy-from-env@npm:1.0.0":
+ version: 1.0.0
+ resolution: "proxy-from-env@npm:1.0.0"
+ checksum: 10c0/c64df9b21f7f820dc882cd6f7f81671840acd28b9688ee3e3e6af47a56ec7f0edcabe5bc96b32b26218b35eeff377bcc27ac27f89b6b21401003e187ff13256f
+ languageName: node
+ linkType: hard
+
+"pump@npm:^3.0.0":
+ version: 3.0.3
+ resolution: "pump@npm:3.0.3"
+ dependencies:
+ end-of-stream: "npm:^1.1.0"
+ once: "npm:^1.3.1"
+ checksum: 10c0/ada5cdf1d813065bbc99aa2c393b8f6beee73b5de2890a8754c9f488d7323ffd2ca5f5a0943b48934e3fcbd97637d0337369c3c631aeb9614915db629f1c75c9
+ languageName: node
+ linkType: hard
+
"punycode.js@npm:^2.3.1":
version: 2.3.1
resolution: "punycode.js@npm:2.3.1"
@@ -4109,6 +5055,15 @@ __metadata:
languageName: node
linkType: hard
+"qs@npm:6.14.0":
+ version: 6.14.0
+ resolution: "qs@npm:6.14.0"
+ dependencies:
+ side-channel: "npm:^1.1.0"
+ checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c
+ languageName: node
+ linkType: hard
+
"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
@@ -4116,6 +5071,17 @@ __metadata:
languageName: node
linkType: hard
+"react-dom@npm:^19.1.1":
+ version: 19.2.0
+ resolution: "react-dom@npm:19.2.0"
+ dependencies:
+ scheduler: "npm:^0.27.0"
+ peerDependencies:
+ react: ^19.2.0
+ checksum: 10c0/fa2cae05248d01288e91523b590ce4e7635b1e13f1344e225f850d722a8da037bf0782f63b1c1d46353334e0c696909b82e582f8cad607948fde6f7646cc18d9
+ languageName: node
+ linkType: hard
+
"react-is@npm:^16.13.1":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
@@ -4123,6 +5089,13 @@ __metadata:
languageName: node
linkType: hard
+"react@npm:^19.1.1":
+ version: 19.2.0
+ resolution: "react@npm:19.2.0"
+ checksum: 10c0/1b6d64eacb9324725bfe1e7860cb7a6b8a34bc89a482920765ebff5c10578eb487e6b46b2f0df263bd27a25edbdae2c45e5ea5d81ae61404301c1a7192c38330
+ languageName: node
+ linkType: hard
+
"readdirp@npm:^4.0.1":
version: 4.1.2
resolution: "readdirp@npm:4.1.2"
@@ -4165,6 +5138,15 @@ __metadata:
languageName: node
linkType: hard
+"request-progress@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "request-progress@npm:3.0.0"
+ dependencies:
+ throttleit: "npm:^1.0.0"
+ checksum: 10c0/d5dcb7155a738572c8781436f6b418e866066a30eea0f99a9ab26b6f0ed6c13637462bba736357de3899b8d30431ee9202ac956a5f8ccdd0d9d1ed0962000d14
+ languageName: node
+ linkType: hard
+
"require-from-string@npm:^2.0.2":
version: 2.0.2
resolution: "require-from-string@npm:2.0.2"
@@ -4212,6 +5194,16 @@ __metadata:
languageName: node
linkType: hard
+"restore-cursor@npm:^3.1.0":
+ version: 3.1.0
+ resolution: "restore-cursor@npm:3.1.0"
+ dependencies:
+ onetime: "npm:^5.1.0"
+ signal-exit: "npm:^3.0.2"
+ checksum: 10c0/8051a371d6aa67ff21625fa94e2357bd81ffdc96267f3fb0fc4aaf4534028343836548ef34c240ffa8c25b280ca35eb36be00b3cb2133fa4f51896d7e73c6b4f
+ languageName: node
+ linkType: hard
+
"retry@npm:^0.12.0":
version: 0.12.0
resolution: "retry@npm:0.12.0"
@@ -4226,6 +5218,13 @@ __metadata:
languageName: node
linkType: hard
+"rfdc@npm:^1.3.0":
+ version: 1.4.1
+ resolution: "rfdc@npm:1.4.1"
+ checksum: 10c0/4614e4292356cafade0b6031527eea9bc90f2372a22c012313be1dcc69a3b90c7338158b414539be863fa95bfcb2ddcd0587be696841af4e6679d85e62c060c7
+ languageName: node
+ linkType: hard
+
"rimraf@npm:^5.0.5":
version: 5.0.10
resolution: "rimraf@npm:5.0.10"
@@ -4327,6 +5326,15 @@ __metadata:
languageName: node
linkType: hard
+"rxjs@npm:^7.5.1":
+ version: 7.8.2
+ resolution: "rxjs@npm:7.8.2"
+ dependencies:
+ tslib: "npm:^2.1.0"
+ checksum: 10c0/1fcd33d2066ada98ba8f21fcbbcaee9f0b271de1d38dc7f4e256bfbc6ffcdde68c8bfb69093de7eeb46f24b1fb820620bf0223706cff26b4ab99a7ff7b2e2c45
+ languageName: node
+ linkType: hard
+
"safe-array-concat@npm:^1.1.2, safe-array-concat@npm:^1.1.3":
version: 1.1.3
resolution: "safe-array-concat@npm:1.1.3"
@@ -4340,6 +5348,13 @@ __metadata:
languageName: node
linkType: hard
+"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.2":
+ version: 5.2.1
+ resolution: "safe-buffer@npm:5.2.1"
+ checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
+ languageName: node
+ linkType: hard
+
"safe-regex-test@npm:^1.1.0":
version: 1.1.0
resolution: "safe-regex-test@npm:1.1.0"
@@ -4351,7 +5366,7 @@ __metadata:
languageName: node
linkType: hard
-"safer-buffer@npm:>= 2.1.2 < 3.0.0":
+"safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4
@@ -4367,6 +5382,13 @@ __metadata:
languageName: node
linkType: hard
+"scheduler@npm:^0.27.0":
+ version: 0.27.0
+ resolution: "scheduler@npm:0.27.0"
+ checksum: 10c0/4f03048cb05a3c8fddc45813052251eca00688f413a3cee236d984a161da28db28ba71bd11e7a3dd02f7af84ab28d39fb311431d3b3772fed557945beb00c452
+ languageName: node
+ linkType: hard
+
"semver@npm:^6.3.1":
version: 6.3.1
resolution: "semver@npm:6.3.1"
@@ -4385,6 +5407,15 @@ __metadata:
languageName: node
linkType: hard
+"semver@npm:^7.7.1":
+ version: 7.7.3
+ resolution: "semver@npm:7.7.3"
+ bin:
+ semver: bin/semver.js
+ checksum: 10c0/4afe5c986567db82f44c8c6faef8fe9df2a9b1d98098fc1721f57c696c4c21cebd572f297fc21002f81889492345b8470473bc6f4aff5fb032a6ea59ea2bc45e
+ languageName: node
+ linkType: hard
+
"set-function-length@npm:^1.2.2":
version: 1.2.2
resolution: "set-function-length@npm:1.2.2"
@@ -4482,6 +5513,13 @@ __metadata:
languageName: node
linkType: hard
+"signal-exit@npm:^3.0.2":
+ version: 3.0.7
+ resolution: "signal-exit@npm:3.0.7"
+ checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912
+ languageName: node
+ linkType: hard
+
"signal-exit@npm:^4.0.1":
version: 4.1.0
resolution: "signal-exit@npm:4.1.0"
@@ -4489,6 +5527,28 @@ __metadata:
languageName: node
linkType: hard
+"slice-ansi@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "slice-ansi@npm:3.0.0"
+ dependencies:
+ ansi-styles: "npm:^4.0.0"
+ astral-regex: "npm:^2.0.0"
+ is-fullwidth-code-point: "npm:^3.0.0"
+ checksum: 10c0/88083c9d0ca67d09f8b4c78f68833d69cabbb7236b74df5d741ad572bbf022deaf243fa54009cd434350622a1174ab267710fcc80a214ecc7689797fe00cb27c
+ languageName: node
+ linkType: hard
+
+"slice-ansi@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "slice-ansi@npm:4.0.0"
+ dependencies:
+ ansi-styles: "npm:^4.0.0"
+ astral-regex: "npm:^2.0.0"
+ is-fullwidth-code-point: "npm:^3.0.0"
+ checksum: 10c0/6c25678db1270d4793e0327620f1e0f9f5bea4630123f51e9e399191bc52c87d6e6de53ed33538609e5eacbd1fab769fae00f3705d08d029f02102a540648918
+ languageName: node
+ linkType: hard
+
"smart-buffer@npm:^4.2.0":
version: 4.2.0
resolution: "smart-buffer@npm:4.2.0"
@@ -4540,6 +5600,27 @@ __metadata:
languageName: node
linkType: hard
+"sshpk@npm:^1.18.0":
+ version: 1.18.0
+ resolution: "sshpk@npm:1.18.0"
+ dependencies:
+ asn1: "npm:~0.2.3"
+ assert-plus: "npm:^1.0.0"
+ bcrypt-pbkdf: "npm:^1.0.0"
+ dashdash: "npm:^1.12.0"
+ ecc-jsbn: "npm:~0.1.1"
+ getpass: "npm:^0.1.1"
+ jsbn: "npm:~0.1.0"
+ safer-buffer: "npm:^2.0.2"
+ tweetnacl: "npm:~0.14.0"
+ bin:
+ sshpk-conv: bin/sshpk-conv
+ sshpk-sign: bin/sshpk-sign
+ sshpk-verify: bin/sshpk-verify
+ checksum: 10c0/e516e34fa981cfceef45fd2e947772cc70dbd57523e5c608e2cd73752ba7f8a99a04df7c3ed751588e8d91956b6f16531590b35d3489980d1c54c38bebcd41b1
+ languageName: node
+ linkType: hard
+
"ssri@npm:^12.0.0":
version: 12.0.0
resolution: "ssri@npm:12.0.0"
@@ -4563,7 +5644,7 @@ __metadata:
languageName: node
linkType: hard
-"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0":
+"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0":
version: 4.2.3
resolution: "string-width@npm:4.2.3"
dependencies:
@@ -4671,6 +5752,13 @@ __metadata:
languageName: node
linkType: hard
+"strip-final-newline@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "strip-final-newline@npm:2.0.0"
+ checksum: 10c0/bddf8ccd47acd85c0e09ad7375409d81653f645fda13227a9d459642277c253d877b68f2e5e4d819fe75733b0e626bac7e954c04f3236f6d196f79c94fa4a96f
+ languageName: node
+ linkType: hard
+
"strip-json-comments@npm:^3.1.1":
version: 3.1.1
resolution: "strip-json-comments@npm:3.1.1"
@@ -4705,6 +5793,15 @@ __metadata:
languageName: node
linkType: hard
+"supports-color@npm:^8.1.1":
+ version: 8.1.1
+ resolution: "supports-color@npm:8.1.1"
+ dependencies:
+ has-flag: "npm:^4.0.0"
+ checksum: 10c0/ea1d3c275dd604c974670f63943ed9bd83623edc102430c05adb8efc56ba492746b6e95386e7831b872ec3807fd89dd8eb43f735195f37b5ec343e4234cc7e89
+ languageName: node
+ linkType: hard
+
"supports-preserve-symlinks-flag@npm:^1.0.0":
version: 1.0.0
resolution: "supports-preserve-symlinks-flag@npm:1.0.0"
@@ -4770,6 +5867,20 @@ __metadata:
languageName: node
linkType: hard
+"throttleit@npm:^1.0.0":
+ version: 1.0.1
+ resolution: "throttleit@npm:1.0.1"
+ checksum: 10c0/4d41a1bf467646b1aa7bec0123b78452a0e302d7344f6a67e43e68434f0a02ea3ba44df050a40c69adeb9cae3cbf6b36b38cfe94bcc3c4a8243c9b63e38e059b
+ languageName: node
+ linkType: hard
+
+"through@npm:^2.3.8":
+ version: 2.3.8
+ resolution: "through@npm:2.3.8"
+ checksum: 10c0/4b09f3774099de0d4df26d95c5821a62faee32c7e96fb1f4ebd54a2d7c11c57fe88b0a0d49cf375de5fee5ae6bf4eb56dbbf29d07366864e2ee805349970d3cc
+ languageName: node
+ linkType: hard
+
"tinybench@npm:^2.9.0":
version: 2.9.0
resolution: "tinybench@npm:2.9.0"
@@ -4811,6 +5922,13 @@ __metadata:
languageName: node
linkType: hard
+"tldts-core@npm:^6.1.86":
+ version: 6.1.86
+ resolution: "tldts-core@npm:6.1.86"
+ checksum: 10c0/8133c29375f3f99f88fce5f4d62f6ecb9532b106f31e5423b27c1eb1b6e711bd41875184a456819ceaed5c8b94f43911b1ad57e25c6eb86e1fc201228ff7e2af
+ languageName: node
+ linkType: hard
+
"tldts-core@npm:^7.0.17":
version: 7.0.17
resolution: "tldts-core@npm:7.0.17"
@@ -4818,6 +5936,17 @@ __metadata:
languageName: node
linkType: hard
+"tldts@npm:^6.1.32":
+ version: 6.1.86
+ resolution: "tldts@npm:6.1.86"
+ dependencies:
+ tldts-core: "npm:^6.1.86"
+ bin:
+ tldts: bin/cli.js
+ checksum: 10c0/27ae7526d9d78cb97b2de3f4d102e0b4321d1ccff0648a7bb0e039ed54acbce86bacdcd9cd3c14310e519b457854e7bafbef1f529f58a1e217a737ced63f0940
+ languageName: node
+ linkType: hard
+
"tldts@npm:^7.0.5":
version: 7.0.17
resolution: "tldts@npm:7.0.17"
@@ -4829,6 +5958,13 @@ __metadata:
languageName: node
linkType: hard
+"tmp@npm:~0.2.3":
+ version: 0.2.5
+ resolution: "tmp@npm:0.2.5"
+ checksum: 10c0/cee5bb7d674bb4ba3ab3f3841c2ca7e46daeb2109eec395c1ec7329a91d52fcb21032b79ac25161a37b2565c4858fefab927af9735926a113ef7bac9091a6e0e
+ languageName: node
+ linkType: hard
+
"to-regex-range@npm:^5.0.1":
version: 5.0.1
resolution: "to-regex-range@npm:5.0.1"
@@ -4838,6 +5974,15 @@ __metadata:
languageName: node
linkType: hard
+"tough-cookie@npm:^5.0.0":
+ version: 5.1.2
+ resolution: "tough-cookie@npm:5.1.2"
+ dependencies:
+ tldts: "npm:^6.1.32"
+ checksum: 10c0/5f95023a47de0f30a902bba951664b359725597d8adeabc66a0b93a931c3af801e1e697dae4b8c21a012056c0ea88bd2bf4dfe66b2adcf8e2f42cd9796fe0626
+ languageName: node
+ linkType: hard
+
"tough-cookie@npm:^6.0.0":
version: 6.0.0
resolution: "tough-cookie@npm:6.0.0"
@@ -4865,7 +6010,7 @@ __metadata:
languageName: node
linkType: hard
-"tree-kill@npm:^1.2.2":
+"tree-kill@npm:1.2.2, tree-kill@npm:^1.2.2":
version: 1.2.2
resolution: "tree-kill@npm:1.2.2"
bin:
@@ -4899,7 +6044,7 @@ __metadata:
languageName: node
linkType: hard
-"tslib@npm:^2.6.2":
+"tslib@npm:^2.1.0, tslib@npm:^2.6.2":
version: 2.8.1
resolution: "tslib@npm:2.8.1"
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
@@ -4948,6 +6093,22 @@ __metadata:
languageName: node
linkType: hard
+"tunnel-agent@npm:^0.6.0":
+ version: 0.6.0
+ resolution: "tunnel-agent@npm:0.6.0"
+ dependencies:
+ safe-buffer: "npm:^5.0.1"
+ checksum: 10c0/4c7a1b813e7beae66fdbf567a65ec6d46313643753d0beefb3c7973d66fcec3a1e7f39759f0a0b4465883499c6dc8b0750ab8b287399af2e583823e40410a17a
+ languageName: node
+ linkType: hard
+
+"tweetnacl@npm:^0.14.3, tweetnacl@npm:~0.14.0":
+ version: 0.14.5
+ resolution: "tweetnacl@npm:0.14.5"
+ checksum: 10c0/4612772653512c7bc19e61923fbf42903f5e0389ec76a4a1f17195859d114671ea4aa3b734c2029ce7e1fa7e5cc8b80580f67b071ecf0b46b5636d030a0102a2
+ languageName: node
+ linkType: hard
+
"type-check@npm:^0.4.0, type-check@npm:~0.4.0":
version: 0.4.0
resolution: "type-check@npm:0.4.0"
@@ -4957,6 +6118,20 @@ __metadata:
languageName: node
linkType: hard
+"type-fest@npm:^0.21.3":
+ version: 0.21.3
+ resolution: "type-fest@npm:0.21.3"
+ checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8
+ languageName: node
+ linkType: hard
+
+"type-fest@npm:^0.8.0":
+ version: 0.8.1
+ resolution: "type-fest@npm:0.8.1"
+ checksum: 10c0/dffbb99329da2aa840f506d376c863bd55f5636f4741ad6e65e82f5ce47e6914108f44f340a0b74009b0cb5d09d6752ae83203e53e98b1192cf80ecee5651636
+ languageName: node
+ linkType: hard
+
"typed-array-buffer@npm:^1.0.2":
version: 1.0.2
resolution: "typed-array-buffer@npm:1.0.2"
@@ -5146,6 +6321,20 @@ __metadata:
languageName: node
linkType: hard
+"universalify@npm:^2.0.0":
+ version: 2.0.1
+ resolution: "universalify@npm:2.0.1"
+ checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a
+ languageName: node
+ linkType: hard
+
+"untildify@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "untildify@npm:4.0.0"
+ checksum: 10c0/d758e624c707d49f76f7511d75d09a8eda7f2020d231ec52b67ff4896bcf7013be3f9522d8375f57e586e9a2e827f5641c7e06ee46ab9c435fc2b2b2e9de517a
+ languageName: node
+ linkType: hard
+
"uri-js@npm:^4.2.2":
version: 4.4.1
resolution: "uri-js@npm:4.4.1"
@@ -5155,6 +6344,26 @@ __metadata:
languageName: node
linkType: hard
+"uuid@npm:^8.3.2":
+ version: 8.3.2
+ resolution: "uuid@npm:8.3.2"
+ bin:
+ uuid: dist/bin/uuid
+ checksum: 10c0/bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54
+ languageName: node
+ linkType: hard
+
+"verror@npm:1.10.0":
+ version: 1.10.0
+ resolution: "verror@npm:1.10.0"
+ dependencies:
+ assert-plus: "npm:^1.0.0"
+ core-util-is: "npm:1.0.2"
+ extsprintf: "npm:^1.2.0"
+ checksum: 10c0/37ccdf8542b5863c525128908ac80f2b476eed36a32cb944de930ca1e2e78584cc435c4b9b4c68d0fc13a47b45ff364b4be43aa74f8804f9050140f660fb660d
+ languageName: node
+ linkType: hard
+
"vite-plugin-cogs-sdk@workspace:packages/vite-plugin":
version: 0.0.0-use.local
resolution: "vite-plugin-cogs-sdk@workspace:packages/vite-plugin"
@@ -5558,7 +6767,7 @@ __metadata:
languageName: node
linkType: hard
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0":
version: 7.0.0
resolution: "wrap-ansi@npm:7.0.0"
dependencies:
@@ -5569,6 +6778,17 @@ __metadata:
languageName: node
linkType: hard
+"wrap-ansi@npm:^6.2.0":
+ version: 6.2.0
+ resolution: "wrap-ansi@npm:6.2.0"
+ dependencies:
+ ansi-styles: "npm:^4.0.0"
+ string-width: "npm:^4.1.0"
+ strip-ansi: "npm:^6.0.0"
+ checksum: 10c0/baad244e6e33335ea24e86e51868fe6823626e3a3c88d9a6674642afff1d34d9a154c917e74af8d845fd25d170c4ea9cf69a47133c3f3656e1252b3d462d9f6c
+ languageName: node
+ linkType: hard
+
"wrap-ansi@npm:^8.1.0":
version: 8.1.0
resolution: "wrap-ansi@npm:8.1.0"
@@ -5580,6 +6800,13 @@ __metadata:
languageName: node
linkType: hard
+"wrappy@npm:1":
+ version: 1.0.2
+ resolution: "wrappy@npm:1.0.2"
+ checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0
+ languageName: node
+ linkType: hard
+
"ws@npm:^8.18.3":
version: 8.18.3
resolution: "ws@npm:8.18.3"
@@ -5632,6 +6859,16 @@ __metadata:
languageName: node
linkType: hard
+"yauzl@npm:^2.10.0":
+ version: 2.10.0
+ resolution: "yauzl@npm:2.10.0"
+ dependencies:
+ buffer-crc32: "npm:~0.2.3"
+ fd-slicer: "npm:~1.1.0"
+ checksum: 10c0/f265002af7541b9ec3589a27f5fb8f11cf348b53cc15e2751272e3c062cd73f3e715bc72d43257de71bbaecae446c3f1b14af7559e8ab0261625375541816422
+ languageName: node
+ linkType: hard
+
"yocto-queue@npm:^0.1.0":
version: 0.1.0
resolution: "yocto-queue@npm:0.1.0"